Selaa lähdekoodia

completed:
1:简化api配置
2:登录添加手机号/设备id
3:内容优化

dxl 3 kuukautta sitten
vanhempi
commit
351afdd612
32 muutettua tiedostoa jossa 1156 lisäystä ja 695 poistoa
  1. 0 3
      .idea/.gitignore
  2. 0 6
      .idea/AndroidProjectSystem.xml
  3. 0 158
      .idea/codeStyles/Project.xml
  4. 0 5
      .idea/codeStyles/codeStyleConfig.xml
  5. 0 6
      .idea/compiler.xml
  6. 0 18
      .idea/deploymentTargetSelector.xml
  7. 0 19
      .idea/gradle.xml
  8. 0 10
      .idea/migrations.xml
  9. 0 9
      .idea/misc.xml
  10. 0 17
      .idea/runConfigurations.xml
  11. 0 6
      .idea/vcs.xml
  12. 100 8
      app/build.gradle.kts
  13. BIN
      app/libs/open_ad_sdk_6.9.1.5.aar
  14. 31 14
      app/src/main/AndroidManifest.xml
  15. 21 17
      app/src/main/java/com/ytpm/hydtw/Constants.java
  16. 202 30
      app/src/main/java/com/ytpm/hydtw/activity/LoginActivity.kt
  17. 1 2
      app/src/main/java/com/ytpm/hydtw/activity/SplashActivity.kt
  18. 51 7
      app/src/main/java/com/ytpm/hydtw/application/DatiApplication.kt
  19. 1 1
      app/src/main/java/com/ytpm/hydtw/dao/UserInfo.kt
  20. 354 94
      app/src/main/java/com/ytpm/hydtw/fragment/DatiFragment.kt
  21. 8 3
      app/src/main/java/com/ytpm/hydtw/network/BaseRetrofit.java
  22. 12 1
      app/src/main/java/com/ytpm/hydtw/network/Callback2.java
  23. 22 39
      app/src/main/java/com/ytpm/hydtw/network/api/MRefrofitInterface.java
  24. 0 60
      app/src/main/java/com/ytpm/hydtw/utils/Base64Decoder.kt
  25. 0 120
      app/src/main/java/com/ytpm/hydtw/utils/GameNetworkUtils.kt
  26. 174 0
      app/src/main/java/com/ytpm/hydtw/utils/LocationUtils.kt
  27. 0 33
      app/src/main/java/com/ytpm/hydtw/utils/MainHandler.java
  28. 148 0
      app/src/main/java/com/ytpm/hydtw/utils/PermissionUtils.kt
  29. 8 6
      app/src/main/res/layout/fragment_dati.xml
  30. 6 0
      build.gradle.kts
  31. 4 3
      gradle/libs.versions.toml
  32. 13 0
      settings.gradle.kts

+ 0 - 3
.idea/.gitignore

@@ -1,3 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml

+ 0 - 6
.idea/AndroidProjectSystem.xml

@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="AndroidProjectSystem">
-    <option name="providerId" value="com.android.tools.idea.GradleProjectSystem" />
-  </component>
-</project>

+ 0 - 158
.idea/codeStyles/Project.xml

@@ -1,158 +0,0 @@
-<component name="ProjectCodeStyleConfiguration">
-  <code_scheme name="Project" version="173">
-    <JavaCodeStyleSettings>
-      <option name="IMPORT_LAYOUT_TABLE">
-        <value>
-          <package name="" withSubpackages="true" static="false" module="true" />
-          <package name="android" withSubpackages="true" static="true" />
-          <package name="androidx" withSubpackages="true" static="true" />
-          <package name="com" withSubpackages="true" static="true" />
-          <package name="junit" withSubpackages="true" static="true" />
-          <package name="net" withSubpackages="true" static="true" />
-          <package name="org" withSubpackages="true" static="true" />
-          <package name="java" withSubpackages="true" static="true" />
-          <package name="javax" withSubpackages="true" static="true" />
-          <package name="" withSubpackages="true" static="true" />
-          <emptyLine />
-          <package name="android" withSubpackages="true" static="false" />
-          <emptyLine />
-          <package name="androidx" withSubpackages="true" static="false" />
-          <emptyLine />
-          <package name="com" withSubpackages="true" static="false" />
-          <emptyLine />
-          <package name="junit" withSubpackages="true" static="false" />
-          <emptyLine />
-          <package name="net" withSubpackages="true" static="false" />
-          <emptyLine />
-          <package name="org" withSubpackages="true" static="false" />
-          <emptyLine />
-          <package name="java" withSubpackages="true" static="false" />
-          <emptyLine />
-          <package name="javax" withSubpackages="true" static="false" />
-          <emptyLine />
-          <package name="" withSubpackages="true" static="false" />
-          <emptyLine />
-        </value>
-      </option>
-    </JavaCodeStyleSettings>
-    <JetCodeStyleSettings>
-      <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
-    </JetCodeStyleSettings>
-    <codeStyleSettings language="XML">
-      <option name="FORCE_REARRANGE_MODE" value="1" />
-      <indentOptions>
-        <option name="CONTINUATION_INDENT_SIZE" value="4" />
-      </indentOptions>
-      <arrangement>
-        <rules>
-          <section>
-            <rule>
-              <match>
-                <AND>
-                  <NAME>xmlns:android</NAME>
-                  <XML_ATTRIBUTE />
-                  <XML_NAMESPACE>^$</XML_NAMESPACE>
-                </AND>
-              </match>
-            </rule>
-          </section>
-          <section>
-            <rule>
-              <match>
-                <AND>
-                  <NAME>xmlns:.*</NAME>
-                  <XML_ATTRIBUTE />
-                  <XML_NAMESPACE>^$</XML_NAMESPACE>
-                </AND>
-              </match>
-              <order>BY_NAME</order>
-            </rule>
-          </section>
-          <section>
-            <rule>
-              <match>
-                <AND>
-                  <NAME>.*:id</NAME>
-                  <XML_ATTRIBUTE />
-                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
-                </AND>
-              </match>
-            </rule>
-          </section>
-          <section>
-            <rule>
-              <match>
-                <AND>
-                  <NAME>.*:name</NAME>
-                  <XML_ATTRIBUTE />
-                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
-                </AND>
-              </match>
-            </rule>
-          </section>
-          <section>
-            <rule>
-              <match>
-                <AND>
-                  <NAME>name</NAME>
-                  <XML_ATTRIBUTE />
-                  <XML_NAMESPACE>^$</XML_NAMESPACE>
-                </AND>
-              </match>
-            </rule>
-          </section>
-          <section>
-            <rule>
-              <match>
-                <AND>
-                  <NAME>style</NAME>
-                  <XML_ATTRIBUTE />
-                  <XML_NAMESPACE>^$</XML_NAMESPACE>
-                </AND>
-              </match>
-            </rule>
-          </section>
-          <section>
-            <rule>
-              <match>
-                <AND>
-                  <NAME>.*</NAME>
-                  <XML_ATTRIBUTE />
-                  <XML_NAMESPACE>^$</XML_NAMESPACE>
-                </AND>
-              </match>
-              <order>BY_NAME</order>
-            </rule>
-          </section>
-          <section>
-            <rule>
-              <match>
-                <AND>
-                  <NAME>.*</NAME>
-                  <XML_ATTRIBUTE />
-                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
-                </AND>
-              </match>
-              <order>ANDROID_ATTRIBUTE_ORDER</order>
-            </rule>
-          </section>
-          <section>
-            <rule>
-              <match>
-                <AND>
-                  <NAME>.*</NAME>
-                  <XML_ATTRIBUTE />
-                  <XML_NAMESPACE>.*</XML_NAMESPACE>
-                </AND>
-              </match>
-              <order>BY_NAME</order>
-            </rule>
-          </section>
-        </rules>
-      </arrangement>
-    </codeStyleSettings>
-    <codeStyleSettings language="kotlin">
-      <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
-    </codeStyleSettings>
-  </code_scheme>
-</component>

+ 0 - 5
.idea/codeStyles/codeStyleConfig.xml

@@ -1,5 +0,0 @@
-<component name="ProjectCodeStyleConfiguration">
-  <state>
-    <option name="USE_PER_PROJECT_SETTINGS" value="true" />
-  </state>
-</component>

+ 0 - 6
.idea/compiler.xml

@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="CompilerConfiguration">
-    <bytecodeTargetLevel target="21" />
-  </component>
-</project>

+ 0 - 18
.idea/deploymentTargetSelector.xml

@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="deploymentTargetSelector">
-    <selectionStates>
-      <SelectionState runConfigName="app">
-        <option name="selectionMode" value="DROPDOWN" />
-        <DropdownSelection timestamp="2025-06-24T08:17:15.280385900Z">
-          <Target type="DEFAULT_BOOT">
-            <handle>
-              <DeviceId pluginId="PhysicalDevice" identifier="serial=000002f6ac59484e" />
-            </handle>
-          </Target>
-        </DropdownSelection>
-        <DialogSelection />
-      </SelectionState>
-    </selectionStates>
-  </component>
-</project>

+ 0 - 19
.idea/gradle.xml

@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="GradleMigrationSettings" migrationVersion="1" />
-  <component name="GradleSettings">
-    <option name="linkedExternalProjectsSettings">
-      <GradleProjectSettings>
-        <option name="testRunner" value="CHOOSE_PER_TEST" />
-        <option name="externalProjectPath" value="$PROJECT_DIR$" />
-        <option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
-        <option name="modules">
-          <set>
-            <option value="$PROJECT_DIR$" />
-            <option value="$PROJECT_DIR$/app" />
-          </set>
-        </option>
-      </GradleProjectSettings>
-    </option>
-  </component>
-</project>

+ 0 - 10
.idea/migrations.xml

@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="ProjectMigrations">
-    <option name="MigrateToGradleLocalJavaHome">
-      <set>
-        <option value="$PROJECT_DIR$" />
-      </set>
-    </option>
-  </component>
-</project>

+ 0 - 9
.idea/misc.xml

@@ -1,9 +0,0 @@
-<project version="4">
-  <component name="ExternalStorageConfigurationManager" enabled="true" />
-  <component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
-    <output url="file://$PROJECT_DIR$/build/classes" />
-  </component>
-  <component name="ProjectType">
-    <option name="id" value="Android" />
-  </component>
-</project>

+ 0 - 17
.idea/runConfigurations.xml

@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="RunConfigurationProducerService">
-    <option name="ignoredProducers">
-      <set>
-        <option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
-        <option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
-        <option value="com.intellij.execution.junit.PatternConfigurationProducer" />
-        <option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
-        <option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
-        <option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
-        <option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
-        <option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
-      </set>
-    </option>
-  </component>
-</project>

+ 0 - 6
.idea/vcs.xml

@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="VcsDirectoryMappings">
-    <mapping directory="$PROJECT_DIR$" vcs="Git" />
-  </component>
-</project>

+ 100 - 8
app/build.gradle.kts

@@ -1,14 +1,101 @@
 plugins {
     alias(libs.plugins.android.application)
     alias(libs.plugins.kotlin.android)
+//    id("mediation-auto-adapter")
 }
 
 android {
 
+    buildFeatures {
+        buildConfig = true  // 启用 BuildConfig 生成
+    }
+    flavorDimensions += "version" // 定义维度
+
+    productFlavors {
+
+        create("lzk") {//乐助客
+            dimension = "version"
+            signingConfig = signingConfigs.getByName("debug")
+            resValue("string", "app_name", "答题王乐助客")
+            buildConfigField("String", "DITCH_ID", "\"2025062503\"")
+            buildConfigField("String", "APP_TYPE", "\"103\"")
+        }
+
+        create("zrb") {//众人帮
+            dimension = "version"
+            signingConfig = signingConfigs.getByName("debug")
+            resValue("string", "app_name", "答题王众人帮")
+            buildConfigField("String", "DITCH_ID", "\"2025062504\"")
+            buildConfigField("String", "APP_TYPE", "\"102\"")
+        }
+
+        create("md") {//秒单
+            dimension = "version"
+            signingConfig = signingConfigs.getByName("debug")
+            resValue("string", "app_name", "答题王秒单")
+            buildConfigField("String", "DITCH_ID", "\"2025062505\"")
+            buildConfigField("String", "APP_TYPE", "\"104\"")
+        }
+
+        create("xwfg") {//兴旺富贵
+            dimension = "version"
+            signingConfig = signingConfigs.getByName("debug")
+            resValue("string", "app_name", "答题王兴旺富贵")
+            buildConfigField("String", "DITCH_ID", "\"2025062506\"")
+            buildConfigField("String", "APP_TYPE", "\"105\"")
+        }
+
+        create("hz") {//合众
+            dimension = "version"
+            signingConfig = signingConfigs.getByName("debug")
+            resValue("string", "app_name", "答题王合众")
+            buildConfigField("String", "DITCH_ID", "\"2025062507\"")
+            buildConfigField("String", "APP_TYPE", "\"106\"")
+        }
+
+        create("sbz") {//赏帮赚
+            dimension = "version"
+            signingConfig = signingConfigs.getByName("debug")
+            resValue("string", "app_name", "答题王赏")
+            buildConfigField("String", "DITCH_ID", "\"2025062501\"")
+            buildConfigField("String", "APP_TYPE", "\"101\"")
+        }
+
+        create("nbcs") {//内部测试包
+            dimension = "version"
+            signingConfig = signingConfigs.getByName("debug")
+            resValue("string", "app_name", "答题王Marx内测渠道")
+            buildConfigField("String", "DITCH_ID", "\"2025062500019\"")
+            buildConfigField("String", "APP_TYPE", "\"200019\"")
+        }
+    }
+
     applicationVariants.configureEach {
         outputs.all {
             if (this is com.android.build.gradle.internal.api.BaseVariantOutputImpl) {
-                val appName = "好运答题王"
+                var appName = ""
+
+                if (flavorName == "lzk") {
+                    appName = "答题王乐助客"
+                }
+                if (flavorName == "zrb") {
+                    appName = "答题王众人帮"
+                }
+                if (flavorName == "md") {
+                    appName = "答题王秒单"
+                }
+                if (flavorName == "xwfg") {
+                    appName = "答题王兴旺富贵"
+                }
+                if (flavorName == "hz") {
+                    appName = "答题王合众"
+                }
+                if (flavorName == "sbz") {
+                    appName = "答题王赏"
+                }
+                if (flavorName == "nbcs") {
+                    appName = "答题王Marx内测渠道"
+                }
                 val versionName = this@configureEach.versionName ?: "unknown"
                 val buildType = this@configureEach.buildType.name
                 val fileName = "${appName}-v${versionName}-${buildType}.apk"
@@ -17,7 +104,6 @@ android {
             }
         }
     }
-
     signingConfigs {
         getByName("debug") {
             storeFile = file("D:\\mg\\project_android\\dati\\app\\datiapp.jks")
@@ -34,8 +120,8 @@ android {
         applicationId = "com.ytpm.hydtw"
         minSdk = 24
         targetSdk = 35
-        versionCode = 1
-        versionName = "1.0.2.1"
+        versionCode = 2
+        versionName = "1.0.6"
         multiDexEnabled = true
         testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
         resValue("string", "app_name", "好运答题王")
@@ -67,7 +153,6 @@ android {
         viewBinding = true
         aidl = true
     }
-
 }
 
 dependencies {
@@ -82,7 +167,7 @@ dependencies {
     implementation(libs.androidx.multidex)
     implementation(libs.wechat.sdk.android.without.mta)
     implementation(libs.utilcodex)
-    implementation(libs.autosize)
+//    implementation(libs.autosize)
     implementation(libs.androidx.appcompat)
     implementation(libs.androidx.core.ktx)
     implementation(libs.androidx.lifecycle.runtime.ktx)
@@ -91,6 +176,7 @@ dependencies {
     androidTestImplementation(libs.androidx.junit)
     androidTestImplementation(libs.androidx.espresso.core)
     implementation("org.threeten:threetenbp:1.5.1")
+    implementation("com.google.android.gms:play-services-location:20.0.0")
 
     //Anythink (Necessary)
     api("com.anythink.sdk:core-taku:6.4.87")
@@ -114,11 +200,17 @@ dependencies {
     api("com.android.support:design:28.0.0")
 
     //Csj
-    api("com.anythink.sdk:adapter-taku-csj:6.4.87.5")
-    api("com.pangle.cn:ads-sdk-pro:6.8.2.0")
+//    api("com.anythink.sdk:adapter-taku-csj:6.4.87.5")
+//    api("com.pangle.cn:ads-sdk-pro:6.8.2.0"){
+//        exclude(group = "com.pangle.cn", module = "ads-sdk-pro")
+//    }
 
     //GDT
     api("com.anythink.sdk:adapter-taku-gdt:6.4.87.1")
     api("com.qq.e.union:union:4.640.1510")
 
+    implementation("com.pangle.cn:mediation-sdk:6.9.1.7") //穿山甲融合SDK
+
+    implementation("com.pangle.cn:mediation-test-tools:6.9.1.7")
+
 }

BIN
app/libs/open_ad_sdk_6.9.1.5.aar


+ 31 - 14
app/src/main/AndroidManifest.xml

@@ -10,6 +10,33 @@
     <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
     <uses-permission android:name="android.permission.GET_TASKS" />
     <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
+        tools:ignore="ProtectedPermissions" />
+    <uses-permission android:name="android.permission.READ_SMS"
+        tools:ignore="PermissionImpliesUnsupportedChromeOsHardware" />
+
+    <!-- 定位权限 -->
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+    <!-- 文件存储权限 (Android 10及以下) -->
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+    <!-- 文件存储权限 (Android 11及以上) -->
+    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
+
+    <!-- SIM卡权限 -->
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+
+    <permission
+        android:name="${applicationId}.openadsdk.permission.TT_PANGOLIN"
+        android:protectionLevel="signature" />
+
+    <uses-permission android:name="${applicationId}.openadsdk.permission.TT_PANGOLIN" />
+
+    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
+        tools:ignore="QueryAllPackagesPermission" />
 
     <application
         android:name="com.ytpm.hydtw.application.DatiApplication"
@@ -21,14 +48,8 @@
         android:supportsRtl="true"
         android:theme="@style/Theme.Dati"
         tools:replace="android:allowBackup"
-        tools:targetApi="31">
-
-        <meta-data
-            android:name="design_width_in_dp"
-            android:value="375" />
-        <meta-data
-            android:name="design_height_in_dp"
-            android:value="812" />
+        tools:targetApi="31"
+        android:hardwareAccelerated="true">
 
         <activity
             android:name="com.ytpm.hydtw.activity.SplashActivity"
@@ -37,24 +58,20 @@
             android:launchMode="singleTask"
             android:screenOrientation="portrait"
             android:theme="@style/Theme.Dati"
-            tools:ignore="DiscouragedApi,LockedOrientationActivity">
-
-        </activity>
+            tools:ignore="DiscouragedApi,LockedOrientationActivity"/>
 
         <activity
             android:name="com.ytpm.hydtw.activity.LoginActivity"
             android:configChanges="orientation|screenSize|keyboardHidden"
             android:exported="true"
+            android:launchMode="singleTop"
             android:screenOrientation="portrait"
             android:theme="@style/Theme.Dati"
             tools:ignore="DiscouragedApi,LockedOrientationActivity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
-
                 <category android:name="android.intent.category.LAUNCHER" />
-
             </intent-filter>
-
         </activity>
 
         <activity

+ 21 - 17
app/src/main/java/com/ytpm/hydtw/Constants.java

@@ -1,21 +1,25 @@
 package com.ytpm.hydtw;
 
 public class Constants {
-  public static final String BuglyAppID = "28d030a2bf";
-  public static String APPID = "1210935703";
-  public static final String POS_ID = "pos_id";
-  public static final String TOKEN = "token";
-  public static final String MIN_VIDEO_DURATION = "minVideoDuration";
-  public static final String MAX_VIDEO_DURATION = "maxVideoDuration";
-  public static final String PLAY_MUTE = "mute";
-  public static final String PLAY_NETWORK = "network";
-  public static final String NEED_COVER = "need_cover";
-  public static final String NEED_PROGRESS = "need_progress";
-  public static final String ENABLE_USER_CONTROL = "enable_user_control";
-  public static final String BUTTON_BIND_TO_CUSTOM_VIEW = "button_bind_to_custom_view";
-  public static final String NONE_OPTION = "none_option";
-  public static final String LOAD_AD_COUNT = "load_ad_count";
-  public static final String ITEMS_PER_AD = "items_per_ad";
-  public static final int VIDEO_DURATION_SETTING_MIN = 5;
-  public static final int VIDEO_DURATION_SETTING_MAX = 60;
+  public static final boolean isDebug = false;
+
+  public static final String TTAD_APPID = "5713373";
+  public static final String TAKU_APPID = "a686ce57b07fc7";
+  public static final String TAKU_KEY = "a43e9b60c240a7c41b0b47ab9659fc27d";
+  public static final String TAKU_BANNER_PID = "b686ceb761ec69";
+  public static final String TAKU_NATIVE_PID = "b686ceb6a6bdf7";
+  public static final String TAKU_REWARD_PID = "b686ceb4adde62";
+  public static final String TAKU_INTERSTITIAL_PID = "b686ceb5bb14cd";
+  public static final String BASE_URL_V2 = "http://advise.ytmdm.com/";//生产
+  public static final String BASE_URL_V2_DEBUG = "http://192.168.1.9:25001/";//测试
+  public static String FULL_URL_V2 = "yt-gateway/";
+  public static String GET_CONFIG = "app-service/wx/defaultConfig";
+  public static String LOGIN = "app-service/wx/login";
+  public static String ANSWER_QUESTION = "app-service/question/answerQuestion";
+  public static String GET_QUESTIONS = "app-service/question/list";
+  public static String ADD_POWER = "app-service/wx/addPower";
+  public static String SAVE_RECORD = "app-service/ad/saveRecord";
+  public static String GET_USER_INFO = "app-service/user/getUserInfo";
+
 }
+

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 202 - 30
app/src/main/java/com/ytpm/hydtw/activity/LoginActivity.kt


+ 1 - 2
app/src/main/java/com/ytpm/hydtw/activity/SplashActivity.kt

@@ -25,7 +25,7 @@ class SplashActivity : FragmentActivity(), ATSplashAdListener {
 
         binding = ActivitySplashBinding.inflate(layoutInflater)
         setContentView(binding.root)
-//        loadAd()
+        loadAd()
         startGetTlTime()
     }
 
@@ -70,7 +70,6 @@ class SplashActivity : FragmentActivity(), ATSplashAdListener {
         }
     }
 
-
     override fun onAdLoadTimeout() {
         LogUtils.e("=======onAdLoadTimeout")
     }

+ 51 - 7
app/src/main/java/com/ytpm/hydtw/application/DatiApplication.kt

@@ -1,14 +1,21 @@
 package com.ytpm.hydtw.application
 
 import android.app.Application
+import android.content.Context
 import android.view.Gravity
+import android.widget.ImageView
 import com.anythink.core.api.ATAdConst
 import com.anythink.core.api.ATSDK
 import com.blankj.utilcode.util.LogUtils
 import com.blankj.utilcode.util.ToastUtils
+import com.bytedance.mtesttools.api.TTMediationTestTool
+import com.bytedance.mtesttools.api.TTMediationTestTool.ImageCallBack
+import com.bytedance.sdk.openadsdk.TTAdConfig
+import com.bytedance.sdk.openadsdk.TTAdConstant
+import com.bytedance.sdk.openadsdk.TTAdSdk
+import com.ytpm.hydtw.Constants
 import com.ytpm.hydtw.R
-import com.ytpm.hydtw.network.BaseRetrofit
-import me.jessyan.autosize.AutoSize
+
 
 class DatiApplication : Application() {
 
@@ -21,25 +28,62 @@ class DatiApplication : Application() {
         super.onCreate()
 
         instance = this
-
-        AutoSize.initCompatMultiProcess(this)
+        initTTAdSdk()
 
         ToastUtils.getDefaultMaker().setMode(ToastUtils.MODE.DARK)
         ToastUtils.getDefaultMaker().setGravity(Gravity.CENTER, 0, 0)
 
         LogUtils.getConfig().setLogSwitch(true)
 
-        ATSDK.setNetworkLogDebug(true)
+        ATSDK.setNetworkLogDebug(false)
         ATSDK.integrationChecking(this)
         ATSDK.setPersonalizedAdStatus(ATAdConst.PRIVACY.PERSIONALIZED_ALLOW_STATUS)
 
         ATSDK.setLocalStrategyAssetPath(this, "localStrategy")
         ATSDK.init(
             applicationContext,
-            "a684009039113d",
-            "afd78bcd2b03126f0c24d7b4e48a439d6"
+            Constants.TAKU_APPID,
+            Constants.TAKU_KEY,
         )
         ATSDK.start()
 
+
+    }
+
+    //穿山甲SDK初始化
+    private fun initTTAdSdk() {
+        TTAdSdk.init(
+            this, TTAdConfig.Builder()
+                .appId(Constants.TTAD_APPID)
+                .appName(resources.getString(R.string.app_name))
+                .titleBarTheme(TTAdConstant.TITLE_BAR_THEME_DARK) //落地页主题
+                .allowShowNotify(true) //是否允许sdk展示通知栏提示
+                .debug(true) //测试阶段打开,可以通过日志排查问题,上线时去除该调用
+                .directDownloadNetworkType(TTAdConstant.NETWORK_STATE_WIFI) //允许直接下载的网络状态集合,没有设置的网络下点击下载apk会有二次确认弹窗,弹窗中会披露应用信息
+                .useMediation(true)//开启聚合功能,默认false
+                .supportMultiProcess(false) //是否支持多进程,true支持
+                .build()
+        )
+
+        TTAdSdk.start(object : TTAdSdk.Callback{
+            override fun success() {
+                LogUtils.e("success: " + TTAdSdk.isSdkReady())
+//                launchMediationTestTool(this@DatiApplication)
+            }
+
+            override fun fail(p0: Int, p1: String?) {
+                LogUtils.e("TTAD fail")
+            }
+
+        })
+    }
+
+    /********************  启动UI测试工具   */ // 启动UI测试工具 **请在测试环境中使用,切勿将测试工具带到生产环境**
+    private fun launchMediationTestTool(context: Context) {
+        TTMediationTestTool.launchTestTools(context, object : ImageCallBack {
+            override fun loadImage(imageView: ImageView?, imageUrl: String?) {
+                // 加载图片到imageView
+            }
+        })
     }
 }

+ 1 - 1
app/src/main/java/com/ytpm/hydtw/dao/UserInfo.kt

@@ -21,7 +21,7 @@ data class UserInfo(
     val wxOpenId: String,
     val platformId: String,
     var lastQuestionId: String,
-    var power: Int,
+    var power: Int = 0,
     var todayAnswerCount: Int,
     var historyAnswerCount: Int,
     var answerRecordList: List<Record>

+ 354 - 94
app/src/main/java/com/ytpm/hydtw/fragment/DatiFragment.kt

@@ -19,18 +19,23 @@ import com.anythink.core.api.AdError
 import com.anythink.interstitial.api.ATInterstitial
 import com.anythink.interstitial.api.ATInterstitialListener
 import com.anythink.nativead.api.ATNative
+import com.anythink.nativead.api.ATNativeAdView
+import com.anythink.nativead.api.ATNativeEventListener
 import com.anythink.nativead.api.ATNativeNetworkListener
 import com.anythink.nativead.api.NativeAd
 import com.anythink.rewardvideo.api.ATRewardVideoAd
 import com.anythink.rewardvideo.api.ATRewardVideoListener
+import com.blankj.utilcode.util.GsonUtils
 import com.blankj.utilcode.util.LogUtils
 import com.blankj.utilcode.util.ToastUtils
 import com.blankj.utilcode.util.ToastUtils.MODE
 import com.gyf.immersionbar.ImmersionBar
+import com.ytpm.hydtw.Constants
 import com.ytpm.hydtw.R
 import com.ytpm.hydtw.adapter.MineAdapter
 import com.ytpm.hydtw.dao.Question
 import com.ytpm.hydtw.dao.Record
+import com.ytpm.hydtw.dao.UserInfo
 import com.ytpm.hydtw.databinding.FragmentDatiBinding
 import com.ytpm.hydtw.loading.GlobalLoading
 import com.ytpm.hydtw.loading.LoadingDialog
@@ -59,20 +64,44 @@ import java.time.format.DateTimeFormatter
 class DatiFragment() : Fragment(), ATRewardVideoListener,
     ATBannerListener {
 
+    private var mBannerView: ATBannerView? = null
     private var atNative: ATNative? = null
     private var interstitialAd: ATInterstitial? = null
     private var startAdTime: String? = null
     private var endAdTime: String? = null
+    private var startBannerAdTime: String? = null
+    private var endBannerAdTime: String? = null
+    private var startNativeAdTime: String? = null
+    private var endNativeAdTime: String? = null
+    private var startInAdTime: String? = null
+    private var endInAdTime: String? = null
     private var mRewardVideoAd: ATRewardVideoAd? = null
+
     private var job: Job? = null
     private var scope: CoroutineScope? = null
+    private var useTimer: Int = 0
+
     private var job1: Job? = null
     private var scope1: CoroutineScope? = null
     private var inAdTime: Int = 0
+
+    private var job2: Job? = null
+    private var scope2: CoroutineScope? = null
+    private var nativeAdTime: Int = 0
+
+    private var job3: Job? = null
+    private var scope3: CoroutineScope? = null
+    private var getTlTime = 30
+    private var pauseGetTlTime = false
+
+    private var job4: Job? = null
+    private var scope4: CoroutineScope? = null
+    private var getTlShowBtnTime = 8
+    private var pauseGetTlShowBtnTime = false
+
     private var getTlCountDownTimer: CountDownTimer? = null
     private var getTlShowBtnCountDownTimer: CountDownTimer? = null
     private var startReloadRewardVideoAd: CountDownTimer? = null
-    private var useTimer: Int = 0
     private var questions: ArrayList<Question>? = arrayListOf()
     private lateinit var binding: FragmentDatiBinding
     private var nowIndex = 0
@@ -81,9 +110,6 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
     private var jrdd = 0
     private var lsdd = 0
 
-    private var getTlTime = 20
-    private var getTlShowBtnTime = 8
-
     private var isGrDialogShow = false
     private var isGetTlDialogShow = false
 
@@ -108,6 +134,7 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
         initData()
         initUserTime()
         initInAdTime()
+//        initNativeTime()
         loadBannerAd()
         loadNativeAd()
         loadInterstitial()
@@ -116,6 +143,7 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
         return binding.root
     }
 
+
     private fun initView() {
 
         val headImg = UserInfoSpUtils().getHeadImg()
@@ -159,9 +187,6 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
         binding.switch2.isChecked = true
 
         startGetTlTime()
-
-        startGetTlShowBtnTime()
-
         initGetTlTime()
 
         binding.dialogGr.setOnClickListener {
@@ -180,6 +205,9 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
         binding.dialogGrClose.setOnClickListener {
             this.isGrDialogShow = false
             binding.dialogGr.visibility = View.GONE
+
+            loadBannerAd()
+            loadNativeAd()
         }
 
         binding.getTlCl.setOnClickListener {
@@ -197,7 +225,17 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
                 binding.dialgoGettlLl.visibility = View.VISIBLE
             }
 
-            getTlShowBtnCountDownTimer?.start()
+            var nowTime = ""
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+                val current = LocalDateTime.now()
+                val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
+                nowTime = current.format(formatter)
+            } else {
+                nowTime = DateTimeUtils.getCurrentDateTime()
+            }
+            binding.dialogGettlTime.text = nowTime
+
+            startGetTlShowBtnTime()
         }
 
         binding.dialgoGettlLl.setOnClickListener { }
@@ -209,6 +247,8 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
             this.isGetTlDialogShow = false
             binding.dialgoGettlLl.visibility = View.GONE
             initGetTlBtnTime()
+            loadBannerAd()
+            loadNativeAd()
         }
 
         binding.a1.setOnClickListener {
@@ -258,9 +298,8 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
             while (isActive) {
                 if (!isInAdPaunse) {
                     inAdTime++
-                    if (inAdTime == 60) {
-
-                        interstitialAd?.show(activity, getATShowConfig1())
+                    if (inAdTime == 30) {
+                        interstitialAd?.load()
                         job1?.cancel()
                         scope1?.cancel()
                         job1 = null
@@ -273,14 +312,45 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
         }
     }
 
+    private fun initNativeTime() {
+        if (job2 == null) {
+            job2 = Job()
+        }
+
+        if (scope2 == null) {
+            scope2 = CoroutineScope(Dispatchers.Main + job2!!)
+        }
+
+        scope2!!.launch {
+            while (isActive) {
+                nativeAdTime++
+                if (nativeAdTime == 40) {
+
+                    if (atNative?.checkAdStatus()?.isLoading == false) {
+                        atNative?.makeAdRequest()
+                    }
+                    job2?.cancel()
+                    scope2?.cancel()
+                    job2 = null
+                    scope2 = null
+                    nativeAdTime = 0
+                }
+                delay(1000)
+            }
+        }
+    }
+
     override fun onPause() {
         super.onPause()
         this.isInAdPaunse = true
+        this.pauseGetTlShowBtnTime = true
     }
 
     override fun onResume() {
         super.onResume()
         this.isInAdPaunse = false
+        this.pauseGetTlShowBtnTime = false
+        getUserInfo()
     }
 
     private fun initDialogGetTl() {
@@ -307,7 +377,14 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
         map["userId"] = UserInfoSpUtils().getUserId()
 
         val requestBody = BaseRetrofit.getRequestBodyByMapToJson(map)
-        BaseRetrofit.getInstance().apiService.answerQuestion(requestBody)
+
+        var url = if (Constants.isDebug) {
+            Constants.ANSWER_QUESTION
+        } else {
+            Constants.FULL_URL_V2 + Constants.ANSWER_QUESTION
+        }
+
+        BaseRetrofit.getInstance().apiService.answerQuestion(url, requestBody)
             .enqueue(object : Callback2<Any>() {
                 override fun success(body: Any?) {
                     val userinfo = UserInfoSpUtils().getUserInfo()
@@ -349,38 +426,45 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
 
     private fun addPower() {
 
+        var url = if (Constants.isDebug) {
+            Constants.ADD_POWER
+        } else {
+            Constants.FULL_URL_V2 + Constants.ADD_POWER
+        }
+
         val userId = UserInfoSpUtils().getUserId()
-        BaseRetrofit.getInstance().apiService.addPower(userId).enqueue(object : Callback2<Any>() {
-            override fun success(body: Any?) {
-                tl++
+        BaseRetrofit.getInstance().apiService.addPower(url, userId)
+            .enqueue(object : Callback2<Any>() {
+                override fun success(body: Any?) {
+                    tl++
 
-                val user = UserInfoSpUtils().getUserInfo()
-                user.power = tl
-                UserInfoSpUtils().changeValue(user)
+                    val user = UserInfoSpUtils().getUserInfo()
+                    user.power = tl
+                    UserInfoSpUtils().changeValue(user)
 
-                isGetTlDialogShow = false
-                binding.dialgoGettlLl.visibility = View.GONE
-                changeLever()
-                initGetTlBtnTime()
-                initGetTlTime()
-            }
+                    isGetTlDialogShow = false
+                    binding.dialgoGettlLl.visibility = View.GONE
+                    changeLever()
+                    initGetTlBtnTime()
+                    initGetTlTime()
+                }
 
-            override fun fail(msg: String?) {
-                ToastUtils
-                    .make()
-                    .setMode(MODE.DARK)
-                    .setGravity(Gravity.CENTER, 0, 0)
-                    .setTopIcon(R.mipmap.icon_fail)
-                    .setDurationIsLong(true)
-                    .show(msg)
-            }
-        })
+                override fun fail(msg: String?) {
+                    ToastUtils
+                        .make()
+                        .setMode(MODE.DARK)
+                        .setGravity(Gravity.CENTER, 0, 0)
+                        .setTopIcon(R.mipmap.icon_fail)
+                        .setDurationIsLong(true)
+                        .show(msg)
+                }
+            })
     }
 
     @SuppressLint("SetTextI18n")
     private fun initGetTlTime() {
         binding.zz.visibility = View.VISIBLE
-        getTlTime = 20
+        getTlTime = 30
         binding.zz.text = "${getTlTime}s"
         getTlCountDownTimer?.start()
     }
@@ -396,25 +480,56 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
 
     private fun startGetTlShowBtnTime() {
 
-        if (getTlShowBtnCountDownTimer != null) {
-            return
+        if (job4 == null) {
+            job4 = Job()
         }
-        this.getTlShowBtnTime = 8
-        getTlShowBtnCountDownTimer =
-            object : CountDownTimer((getTlShowBtnTime * 1000).toLong(), 1000) {
-                @SuppressLint("SetTextI18n")
-                override fun onTick(millisUntilFinished: Long) {
-                    val secondsRemaining = millisUntilFinished / 1000
-                    getTlShowBtnTime--
-                    binding.dialgoGettlTime.text = "${secondsRemaining}s"
-                }
+        if (scope4 == null) {
+            scope4 = CoroutineScope(Dispatchers.Main + job4!!)
+        }
+
 
-                override fun onFinish() {
-                    binding.dialgoGettlTime.visibility = View.GONE
-                    binding.dialotGettlBtnTx.visibility = View.VISIBLE
-                    binding.getTlDialogClose.visibility = View.VISIBLE
+        scope4!!.launch {
+            while (isActive) {
+                if (!pauseGetTlShowBtnTime) {
+                    getTlShowBtnTime--
+                    if (getTlShowBtnTime <= 0) {
+                        binding.dialgoGettlTime.visibility = View.GONE
+                        binding.dialotGettlBtnTx.visibility = View.VISIBLE
+                        binding.getTlDialogClose.visibility = View.VISIBLE
+
+                        job4?.cancel()
+                        scope4?.cancel()
+                        job4 = null
+                        scope4 = null
+                        getTlShowBtnTime = 8
+                    } else {
+                        binding.dialgoGettlTime.text = "${getTlShowBtnTime}s"
+                    }
                 }
+                delay(1000)
             }
+        }
+//
+//        if (getTlShowBtnCountDownTimer != null) {
+//            return
+//        }
+//        this.getTlShowBtnTime = 8
+//        getTlShowBtnCountDownTimer =
+//            object : CountDownTimer((getTlShowBtnTime * 1000).toLong(), 1000) {
+//                @SuppressLint("SetTextI18n")
+//                override fun onTick(millisUntilFinished: Long) {
+//                    val secondsRemaining = millisUntilFinished / 1000
+//                    getTlShowBtnTime--
+//                    binding.dialgoGettlTime.text = "${secondsRemaining}s"
+//                }
+//
+//                override fun onFinish() {
+//                    getTlShowBtnTime = 0
+//                    binding.dialgoGettlTime.visibility = View.GONE
+//                    binding.dialotGettlBtnTx.visibility = View.VISIBLE
+//                    binding.getTlDialogClose.visibility = View.VISIBLE
+//                }
+//            }
     }
 
     private fun startGetTlTime() {
@@ -423,7 +538,7 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
             return
         }
 
-        this.getTlTime = 20
+        this.getTlTime = 30
         getTlCountDownTimer = object : CountDownTimer((getTlTime * 1000).toLong(), 1000) {
             @SuppressLint("SetTextI18n")
             override fun onTick(millisUntilFinished: Long) {
@@ -433,6 +548,7 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
             }
 
             override fun onFinish() {
+                getTlTime = 0
                 binding.zz.visibility = View.GONE
             }
         }
@@ -470,8 +586,12 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
     }
 
     private fun initData() {
-
-        BaseRetrofit.getInstance().apiService.questions.enqueue(object :
+        var url = if (Constants.isDebug) {
+            Constants.GET_QUESTIONS
+        } else {
+            Constants.FULL_URL_V2 + Constants.GET_QUESTIONS
+        }
+        BaseRetrofit.getInstance().apiService.getQuestions(url).enqueue(object :
             Callback2<List<Question>>() {
             override fun success(body: List<Question>?) {
                 binding.answerCl.visibility = View.VISIBLE
@@ -644,8 +764,9 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
 
     private fun loadAd() {
         if (mRewardVideoAd == null) {
-            mRewardVideoAd = ATRewardVideoAd(context, "b68400aae18fc0")
+            mRewardVideoAd = ATRewardVideoAd(context, Constants.TAKU_REWARD_PID)
         }
+
         val userid = UserInfoSpUtils().getUserInfo().userId
         val userdata = UserInfoSpUtils().getUserInfo().nickName
         val localMap: MutableMap<String, Any> = HashMap()
@@ -716,8 +837,10 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
 
     override fun onRewardedVideoAdClosed(p0: ATAdInfo?) {
         LogUtils.e("DFDFDF=onRewardedVideoAdClosed${p0.toString()}")
+        loadBannerAd()
+        loadNativeAd()
         if (!isRewardedVideoFinish) {
-            ToastUtils.showShort("请观看完广告再关闭!")
+            ToastUtils.showLong("获取奖励失败,请观看完广告再关闭!")
         }
     }
 
@@ -726,7 +849,7 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
     }
 
     override fun onReward(p0: ATAdInfo?) {
-
+        isRewardedVideoFinish = true
         LogUtils.e("DFDFDF=onReward${p0.toString()}")
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
             val current = LocalDateTime.now()
@@ -736,16 +859,16 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
             endAdTime = DateTimeUtils.getCurrentDateTime()
         }
 
-        saveRecord(p0)
+        saveRecord(p0, startAdTime.toString(), endAdTime.toString())
     }
 
-    private fun saveRecord(p0: ATAdInfo?) {
+    private fun saveRecord(p0: ATAdInfo?, startAdTime: String, endAdTime: String) {
 
         if (p0 == null) return
         val map = HashMap<String, Any>()
         map["adSourceId"] = p0.adsourceId.toInt()
-        map["beginTime"] = startAdTime.toString()
-        map["finishTime"] = endAdTime.toString()
+        map["beginTime"] = startAdTime
+        map["finishTime"] = endAdTime
         map["networkFormId"] = p0.networkFirmId
         map["networkName"] = p0.networkName
         map["networkPlacementId"] = p0.networkPlacementId
@@ -760,45 +883,115 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
         map["resultJson"] = p0.toString()
 
         val body = BaseRetrofit.getRequestBodyByMapToJson(map)
+        var url = if (Constants.isDebug) {
+            Constants.SAVE_RECORD
+        } else {
+            Constants.FULL_URL_V2 + Constants.SAVE_RECORD
+        }
+        BaseRetrofit.getInstance().apiService.saveRecord(url, body)
+            .enqueue(object : Callback2<Any>() {
+                override fun success(body: Any?) {
+                    if (p0.adSourceAdType == 1) addPower()
+                    LogUtils.e("dfdfdfdf广告同步成功!")
+                }
 
-        BaseRetrofit.getInstance().apiService.saveRecord(body).enqueue(object : Callback2<Any>() {
-            override fun success(body: Any?) {
-                addPower()
-                LogUtils.e("dfdfdfdf广告同步成功!")
-            }
-
-            override fun fail(msg: String?) {
-                ToastUtils.showShort(msg)
-            }
-        })
+                override fun fail(msg: String?) {
+                    ToastUtils.showShort(msg)
+                }
+            })
     }
 
     private fun loadNativeAd() {
         if (atNative == null) {
-            atNative = ATNative(context, "b68400acd7390c", object : ATNativeNetworkListener {
-                override fun onNativeAdLoaded() {
-                    val nativeAd: NativeAd? = atNative?.getNativeAd(getATShowConfig())
-                    try {
-                        nativeAd?.renderAdContainer(binding.fragmentDatiContentAd, null)
-                    } catch (e: Exception) {
-                        e.printStackTrace()
+            atNative =
+                ATNative(context, Constants.TAKU_NATIVE_PID, object : ATNativeNetworkListener {
+                    override fun onNativeAdLoaded() {
+                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+                            val current = LocalDateTime.now()
+                            val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
+                            startNativeAdTime = current.format(formatter)
+                        } else {
+                            startNativeAdTime = DateTimeUtils.getCurrentDateTime()
+                        }
+                        val nativeAd: NativeAd? = atNative?.getNativeAd(getATShowConfig())
+                        nativeAd?.setNativeEventListener(object : ATNativeEventListener {
+                            override fun onAdImpressed(
+                                p0: ATNativeAdView?,
+                                p1: ATAdInfo?
+                            ) {
+                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+                                    val current = LocalDateTime.now()
+                                    val formatter =
+                                        DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
+                                    endNativeAdTime = current.format(formatter)
+                                } else {
+                                    endNativeAdTime = DateTimeUtils.getCurrentDateTime()
+                                }
+                                saveRecord(
+                                    p1,
+                                    startNativeAdTime.toString(),
+                                    endNativeAdTime.toString()
+                                )
+//                            reloadNativeAd()
+                                LogUtils.e("dfdfdfdfonAdImpressed${p1.toString()}")
+                            }
+
+                            override fun onAdClicked(
+                                p0: ATNativeAdView?,
+                                p1: ATAdInfo?
+                            ) {
+                                LogUtils.e("dfdfdfdfonAdImpressed${p1.toString()}")
+                            }
+
+                            override fun onAdVideoStart(p0: ATNativeAdView?) {
+
+                            }
+
+                            override fun onAdVideoEnd(p0: ATNativeAdView?) {
+                            }
+
+                            override fun onAdVideoProgress(
+                                p0: ATNativeAdView?,
+                                p1: Int
+                            ) {
+                                LogUtils.e("dfdfdfdfonAdVideoProgress}")
+                            }
+
+                        })
+                        try {
+                            nativeAd?.renderAdContainer(binding.fragmentDatiContentAd, null)
+                        } catch (e: Exception) {
+                            e.printStackTrace()
+                        }
                     }
-                }
 
-                override fun onNativeAdLoadFail(adError: AdError) {
-                    LogUtils.e("onNativeAdLoadFail:" + adError.fullErrorInfo)
-                    atNative = null
-                    loadNativeAd()
-                }
-            })
+                    override fun onNativeAdLoadFail(adError: AdError) {
+                        LogUtils.e("onNativeAdLoadFail:" + adError.fullErrorInfo)
+                        atNative = null
+                    }
+                })
         }
+
         binding.fragmentDatiContentAd.removeAllViews()
-        atNative?.makeAdRequest()
+        val userid = UserInfoSpUtils().getUserInfo().userId
+        val userdata = UserInfoSpUtils().getUserInfo().nickName
+        val localMap: MutableMap<String, Any> = HashMap()
+        localMap[ATAdConst.KEY.USER_ID] = userid
+        localMap[ATAdConst.KEY.USER_CUSTOM_DATA] = userdata
+        atNative?.setLocalExtra(localMap)
+        if (atNative?.checkAdStatus()?.isLoading == false) atNative?.makeAdRequest()
     }
 
     private fun loadInterstitial() {
 
-        interstitialAd = ATInterstitial(context, "b68400ac31936e")
+        interstitialAd = ATInterstitial(context, Constants.TAKU_INTERSTITIAL_PID)
+
+        val userid = UserInfoSpUtils().getUserInfo().userId
+        val userdata = UserInfoSpUtils().getUserInfo().nickName
+        val localMap: MutableMap<String, Any> = HashMap()
+        localMap[ATAdConst.KEY.USER_ID] = userid
+        localMap[ATAdConst.KEY.USER_CUSTOM_DATA] = userdata
+        interstitialAd?.setLocalExtra(localMap)
         interstitialAd?.setNativeAdCustomRender { mixNativeAd, atAdInfo ->
             MediationNativeAdUtil.getViewFromNativeAd(
                 context,
@@ -810,10 +1003,20 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
         interstitialAd?.setAdListener(object : ATInterstitialListener {
             override fun onInterstitialAdLoaded() {
                 LogUtils.e("==========onInterstitialAdLoaded")
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+                    val current = LocalDateTime.now()
+                    val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
+                    startInAdTime = current.format(formatter)
+                } else {
+                    startInAdTime = DateTimeUtils.getCurrentDateTime()
+                }
+                interstitialAd?.show(activity, getATShowConfig1())
+
             }
 
             override fun onInterstitialAdLoadFail(p0: AdError?) {
                 LogUtils.e("===========onInterstitialAdLoadFail")
+                initInAdTime()
             }
 
             override fun onInterstitialAdClicked(p0: ATAdInfo?) {
@@ -821,7 +1024,16 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
             }
 
             override fun onInterstitialAdShow(p0: ATAdInfo?) {
-                LogUtils.e("=============onInterstitialAdShow")
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+                    val current = LocalDateTime.now()
+                    val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
+                    endInAdTime = current.format(formatter)
+                } else {
+                    endInAdTime = DateTimeUtils.getCurrentDateTime()
+                }
+
+                saveRecord(p0, startInAdTime.toString(), endInAdTime.toString())
+                LogUtils.e("=============onInterstitialAdShow${p0.toString()}")
             }
 
             override fun onInterstitialAdClose(p0: ATAdInfo?) {
@@ -829,7 +1041,6 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
             }
 
             override fun onInterstitialAdVideoStart(p0: ATAdInfo?) {
-                interstitialAd?.load()
                 LogUtils.e("===========onInterstitialAdVideoStart")
             }
 
@@ -847,13 +1058,21 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
     }
 
     private fun loadBannerAd() {
-        val mBannerView = ATBannerView(context)
-        mBannerView.setPlacementId("b68400aba2a385")
-        mBannerView.setShowConfig(getATShowConfig())
-        mBannerView.setBannerAdListener(this)
+
+        mBannerView = ATBannerView(context)
+        mBannerView?.setPlacementId(Constants.TAKU_BANNER_PID)
+        mBannerView?.setShowConfig(getATShowConfig())
+        mBannerView?.setBannerAdListener(this)
         binding.fragmentDatiBanner.removeAllViews()
         binding.fragmentDatiBanner.addView(mBannerView)
-        mBannerView.loadAd()
+
+        val userid = UserInfoSpUtils().getUserInfo().userId
+        val userdata = UserInfoSpUtils().getUserInfo().nickName
+        val localMap: MutableMap<String, Any> = HashMap()
+        localMap[ATAdConst.KEY.USER_ID] = userid
+        localMap[ATAdConst.KEY.USER_CUSTOM_DATA] = userdata
+        mBannerView?.setLocalExtra(localMap)
+        if (mBannerView?.checkAdStatus()?.isLoading == false) mBannerView?.loadAd()
     }
 
     private fun getATShowConfig(): ATShowConfig {
@@ -873,6 +1092,14 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
     }
 
     override fun onBannerLoaded() {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            val current = LocalDateTime.now()
+            val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
+            startBannerAdTime = current.format(formatter)
+        } else {
+            startBannerAdTime = DateTimeUtils.getCurrentDateTime()
+        }
+
         LogUtils.e("dfdfdf onBannerLoaded")
     }
 
@@ -885,7 +1112,16 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
     }
 
     override fun onBannerShow(p0: ATAdInfo?) {
-        LogUtils.e("dfdfdf onBannerShow")
+        LogUtils.e("dfdfdf onBannerShow${p0.toString()}")
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            val current = LocalDateTime.now()
+            val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
+            endBannerAdTime = current.format(formatter)
+        } else {
+            endBannerAdTime = DateTimeUtils.getCurrentDateTime()
+        }
+        saveRecord(p0, startBannerAdTime.toString(), endBannerAdTime.toString())
+
     }
 
     override fun onBannerClose(p0: ATAdInfo?) {
@@ -899,4 +1135,28 @@ class DatiFragment() : Fragment(), ATRewardVideoListener,
     override fun onBannerAutoRefreshFail(p0: AdError?) {
         LogUtils.e("dfdfdf onBannerAutoRefreshFail")
     }
+
+    private fun getUserInfo() {
+        var url = if (Constants.isDebug) {
+            Constants.GET_USER_INFO
+        } else {
+            Constants.FULL_URL_V2 + Constants.GET_USER_INFO
+        }
+        BaseRetrofit.getInstance().apiService.getUserInfo(url, UserInfoSpUtils().getUserId())
+            .enqueue(object : Callback2<UserInfo>() {
+                override fun success(body: UserInfo?) {
+                    body?.let { UserInfoSpUtils().putUserInfo(it) }
+                    jrdd = UserInfoSpUtils().getTodayAnswerCount()
+                    lsdd = UserInfoSpUtils().getHistoryAnswerCount()
+
+                    binding.jrddTv.text = "今日答题: ${jrdd}题"
+                    binding.lsddTv.text = "历史答题: ${lsdd}题"
+                    initDialogGetTl()
+                }
+
+                override fun fail(msg: String?) {
+                    ToastUtils.showShort(msg)
+                }
+            })
+    }
 }

+ 8 - 3
app/src/main/java/com/ytpm/hydtw/network/BaseRetrofit.java

@@ -1,8 +1,7 @@
 package com.ytpm.hydtw.network;
 
-import static com.ytpm.hydtw.network.api.api.BASE_URL_V2;
-
 import com.blankj.utilcode.util.LogUtils;
+import com.ytpm.hydtw.Constants;
 import com.ytpm.hydtw.network.api.MRefrofitInterface;
 
 import org.json.JSONObject;
@@ -45,8 +44,14 @@ public class BaseRetrofit {
 
     private BaseRetrofit() {
 
+        String baseUrl;
+        if (Constants.isDebug) {
+            baseUrl = Constants.BASE_URL_V2_DEBUG;
+        } else {
+            baseUrl = Constants.BASE_URL_V2;
+        }
         this.apiService = new Retrofit.Builder()
-                .baseUrl(BASE_URL_V2)
+                .baseUrl(baseUrl)
                 .addConverterFactory(GsonConverterFactory.create())
                 .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                 .build().create(MRefrofitInterface.class);

+ 12 - 1
app/src/main/java/com/ytpm/hydtw/network/Callback2.java

@@ -1,7 +1,9 @@
 package com.ytpm.hydtw.network;
 
+import com.blankj.utilcode.util.ActivityUtils;
 import com.blankj.utilcode.util.LogUtils;
 import com.google.gson.Gson;
+import com.ytpm.hydtw.activity.LoginActivity;
 import com.ytpm.hydtw.loading.GlobalLoading;
 import com.ytpm.hydtw.network.api.Result;
 
@@ -40,8 +42,13 @@ public abstract class Callback2<T> implements Callback<Result<T>> {
                 LogUtils.e("dfdfdf response body", new Gson().toJson(response.body().getData()));
                 int code = body.getCode();
                 String reason = body.getMessage();
+                LogUtils.e("dfdfdf===========", code);
+                LogUtils.e("dfdfdf===========", reason);
                 if (code == 200) {
                     success(body.getData());
+                } else if (code == 301) {
+                    ActivityUtils.startActivity(LoginActivity.class);
+                    fail(reason);
                 } else {
                     fail(reason);
                 }
@@ -54,6 +61,10 @@ public abstract class Callback2<T> implements Callback<Result<T>> {
 
         final String msg;
         switch (response.code()) {
+            case 301:
+                msg = response.message();
+                ActivityUtils.startActivity(LoginActivity.class);
+                break;
             case 400:
                 msg = "参数错误";
                 break;
@@ -68,7 +79,7 @@ public abstract class Callback2<T> implements Callback<Result<T>> {
 
     @Override
     public void onFailure(Call<Result<T>> call, Throwable t) {
-        LogUtils.e("Call onFailure" + t.getMessage() +"||");
+        LogUtils.e("Call onFailure" + t.getMessage() + "||");
         GlobalLoading.getInstance().dismiss();
 
         if (t instanceof HttpError) {

+ 22 - 39
app/src/main/java/com/ytpm/hydtw/network/api/MRefrofitInterface.java

@@ -1,6 +1,5 @@
 package com.ytpm.hydtw.network.api;
 
-import com.ytpm.hydtw.dao.Config;
 import com.ytpm.hydtw.dao.Question;
 import com.ytpm.hydtw.dao.UserInfo;
 
@@ -12,51 +11,35 @@ import retrofit2.http.Body;
 import retrofit2.http.GET;
 import retrofit2.http.POST;
 import retrofit2.http.Query;
+import retrofit2.http.Url;
 
 /**
  * @author mmmmg
  * @description: 网络请求接口
  * @date :2025/06/12 10:22
  */
+
 public interface MRefrofitInterface {
 
+    @GET
+    Call<Result<String>> getConfigs(@Url String url, @Query("appType") int appType);
+
+    @POST
+    Call<Result<UserInfo>> login(@Url String url, @Body RequestBody requestBody);
+
+    @POST
+    Call<Result<Object>> answerQuestion(@Url String url, @Body RequestBody requestBody);
+
+    @GET
+    Call<Result<List<Question>>> getQuestions(@Url String url);
 
-    //--------------------------dev---------------------------//
-//    @GET("app-service/wx/defaultConfig")
-//    Call<Result<Config>> getConfigs();
-//
-//    @POST("app-service/wx/login")
-//    Call<Result<UserInfo>> login(@Body RequestBody requestBody);
-//
-//    @POST("app-service/question/answerQuestion")
-//    Call<Result<Object>> answerQuestion(@Body RequestBody requestBody);
-//
-//    @GET("app-service/question/list")
-//    Call<Result<List<Question>>> getQuestions();
-//
-//    @GET("app-service/wx/addPower")
-//    Call<Result<Object>> addPower(@Query("userId") String userId);
-//
-//    @POST("app-service/ad/saveRecord")
-//    Call<Result<Object>> saveRecord(@Body RequestBody requestBody);
-
-
-    //--------------------------prod---------------------------//
-    @GET("yt-gateway/app-service/wx/defaultConfig")
-    Call<Result<Config>> getConfigs();
-
-    @POST("yt-gateway/app-service/wx/login")
-    Call<Result<UserInfo>> login(@Body RequestBody requestBody);
-
-    @POST("yt-gateway/app-service/question/answerQuestion")
-    Call<Result<Object>> answerQuestion(@Body RequestBody requestBody);
-
-    @GET("yt-gateway/app-service/question/list")
-    Call<Result<List<Question>>> getQuestions();
-
-    @GET("yt-gateway/app-service/wx/addPower")
-    Call<Result<Object>> addPower(@Query("userId") String userId);
-
-    @POST("yt-gateway/app-service/ad/saveRecord")
-    Call<Result<Object>> saveRecord(@Body RequestBody requestBody);
+    @GET
+    Call<Result<Object>> addPower(@Url String url, @Query("userId") String userId);
+
+    @POST
+    Call<Result<Object>> saveRecord(@Url String url, @Body RequestBody requestBody);
+
+    @GET
+    Call<Result<UserInfo>> getUserInfo(@Url String url, @Query("userId") String userId);
 }
+

+ 0 - 60
app/src/main/java/com/ytpm/hydtw/utils/Base64Decoder.kt

@@ -1,60 +0,0 @@
-package com.ytpm.hydtw.utils
-
-import android.util.Base64
-import java.nio.charset.StandardCharsets
-
-/**
- * Base64 解密工具类
- */
-object Base64Decoder {
-    /**
-     * 简单 Base64 解密(适用于文本数据)
-     * @param base64String Base64 编码的字符串
-     * @return 解密后的字符串,失败返回空字符串
-     */
-    fun decodeToString(base64String: String): String {
-        return try {
-            // 使用 DEFAULT 模式,支持标准 Base64 字符集和填充符
-            val decodedBytes = Base64.decode(base64String, Base64.DEFAULT)
-            String(decodedBytes, StandardCharsets.UTF_8)
-        } catch (e: Exception) {
-            e.printStackTrace()
-            ""
-        }
-    }
-
-    /**
-     * 解密为字节数组(适用于二进制数据)
-     * @param base64String Base64 编码的字符串
-     * @return 解密后的字节数组,失败返回空数组
-     */
-    fun decodeToBytes(base64String: String): ByteArray {
-        return try {
-            Base64.decode(base64String, Base64.DEFAULT)
-        } catch (e: Exception) {
-            e.printStackTrace()
-            byteArrayOf()
-        }
-    }
-
-    /**
-     * 带填充符的 Base64 解密(某些服务端可能省略填充符)
-     */
-    fun decodeWithPadding(base64String: String): String {
-        // 补全填充符(=)
-        val paddedString = padBase64(base64String)
-        return decodeToString(paddedString)
-    }
-
-    /**
-     * 补全 Base64 填充符
-     */
-    private fun padBase64(base64String: String): String {
-        var result = base64String
-        val missingPadding = 4 - (result.length % 4)
-        if (missingPadding != 4 && missingPadding != 0) {
-            result += "=".repeat(missingPadding)
-        }
-        return result
-    }
-}

+ 0 - 120
app/src/main/java/com/ytpm/hydtw/utils/GameNetworkUtils.kt

@@ -1,120 +0,0 @@
-package com.ytpm.hydtw.utils
-
-import android.content.Context
-import android.net.ConnectivityManager
-import android.net.NetworkCapabilities
-import android.net.wifi.WifiManager
-import android.os.Build
-import android.text.format.Formatter
-import java.net.Inet4Address
-import java.net.NetworkInterface
-import java.util.*
-
-class GameNetworkUtils(private val context: Context) {
-
-    /**
-     * 获取当前连接的网络类型
-     */
-    fun getConnectionType(): String {
-        val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
-
-        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-            val network = connectivityManager.activeNetwork ?: return "无连接"
-            val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return "无连接"
-
-            when {
-                capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> "Wi-Fi"
-                capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> "移动数据"
-                capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> "以太网"
-                else -> "其他网络"
-            }
-        } else {
-            @Suppress("DEPRECATION")
-            val networkInfo = connectivityManager.activeNetworkInfo
-            networkInfo?.typeName ?: "无连接"
-        }
-    }
-
-    /**
-     * 获取 Wi-Fi 连接的 IP 地址
-     */
-    fun getWifiIpAddress(): String? {
-        val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
-        if (!wifiManager.isWifiEnabled) {
-            return null
-        }
-
-        val ipAddress = wifiManager.connectionInfo.ipAddress
-
-        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
-            Formatter.formatIpAddress(ipAddress)
-        } else {
-            String.format(
-                "%d.%d.%d.%d",
-                (ipAddress and 0xff),
-                (ipAddress shr 8 and 0xff),
-                (ipAddress shr 16 and 0xff),
-                (ipAddress shr 24 and 0xff)
-            )
-        }
-    }
-
-    /**
-     * 获取移动数据连接的 IP 地址
-     */
-    fun getMobileIpAddress(): String? {
-        return try {
-            val interfaces = Collections.list(NetworkInterface.getNetworkInterfaces())
-            for (intf in interfaces) {
-                // 查找移动数据接口(通常以 rmnet 或 ppp 开头)
-                if (intf.name.startsWith("rmnet") || intf.name.startsWith("ppp")) {
-                    val addrs = Collections.list(intf.inetAddresses)
-                    for (addr in addrs) {
-                        if (!addr.isLoopbackAddress && addr is Inet4Address) {
-                            return addr.hostAddress
-                        }
-                    }
-                }
-            }
-            null
-        } catch (e: Exception) {
-            e.printStackTrace()
-            null
-        }
-    }
-
-    /**
-     * 获取当前连接的 IP 地址(自动判断网络类型)
-     */
-    fun getCurrentIpAddress(): String? {
-        return when (getConnectionType()) {
-            "Wi-Fi" -> getWifiIpAddress()
-            "移动数据" -> getMobileIpAddress()
-            else -> null
-        }
-    }
-
-    /**
-     * 获取所有网络接口的 IP 地址
-     */
-    fun getAllIpAddresses(): List<String> {
-        val ipAddresses = mutableListOf<String>()
-
-        try {
-            val interfaces = Collections.list(NetworkInterface.getNetworkInterfaces())
-            for (intf in interfaces) {
-                val addrs = Collections.list(intf.inetAddresses)
-                for (addr in addrs) {
-                    if (!addr.isLoopbackAddress) {
-                        val sAddr = addr.hostAddress
-                        ipAddresses.add(sAddr)
-                    }
-                }
-            }
-        } catch (e: Exception) {
-            e.printStackTrace()
-        }
-
-        return ipAddresses
-    }
-}

+ 174 - 0
app/src/main/java/com/ytpm/hydtw/utils/LocationUtils.kt

@@ -0,0 +1,174 @@
+package com.ytpm.hydtw.utils
+import android.annotation.SuppressLint
+import android.content.Context
+import android.content.pm.PackageManager
+import android.location.Address
+import android.location.Geocoder
+import android.location.Location
+import android.location.LocationListener
+import android.location.LocationManager
+import android.os.Bundle
+import android.os.Looper
+import androidx.core.content.ContextCompat
+import kotlinx.coroutines.*
+import java.io.IOException
+import java.util.*
+
+class LocationUtils(private val context: Context) {
+    private val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
+    private val geocoder = Geocoder(context, Locale.getDefault())
+    private var locationListener: LocationListener? = null
+
+    // 检查定位权限
+    fun hasLocationPermission(): Boolean {
+        return ContextCompat.checkSelfPermission(
+            context,
+            android.Manifest.permission.ACCESS_FINE_LOCATION
+        ) == PackageManager.PERMISSION_GRANTED ||
+                ContextCompat.checkSelfPermission(
+                    context,
+                    android.Manifest.permission.ACCESS_COARSE_LOCATION
+                ) == PackageManager.PERMISSION_GRANTED
+    }
+
+    // 检查位置服务是否启用
+    fun isLocationServiceEnabled(): Boolean {
+        return try {
+            val gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
+            val networkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
+            gpsEnabled || networkEnabled
+        } catch (e: Exception) {
+            false
+        }
+    }
+
+    // 获取最后一次已知位置
+    @SuppressLint("MissingPermission")
+    suspend fun getLastLocation(): Location? = withContext(Dispatchers.IO) {
+        return@withContext try {
+            var bestLocation: Location? = null
+
+            // 尝试从GPS获取位置
+            val gpsLocation = if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
+                locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)
+            } else {
+                null
+            }
+
+            // 尝试从网络获取位置
+            val networkLocation = if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
+                locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER)
+            } else {
+                null
+            }
+
+            // 选择更精确的位置
+            if (gpsLocation != null && networkLocation != null) {
+                bestLocation = if (gpsLocation.accuracy > networkLocation.accuracy)
+                    gpsLocation else networkLocation
+            } else {
+                bestLocation = gpsLocation ?: networkLocation
+            }
+
+            bestLocation
+        } catch (e: Exception) {
+            e.printStackTrace()
+            null
+        }
+    }
+
+    // 获取当前位置
+    @SuppressLint("MissingPermission")
+    suspend fun getCurrentLocation(timeoutMillis: Long = 30000): Location? =
+        withContext(Dispatchers.Main) {
+            return@withContext suspendCancellableCoroutine { continuation ->
+                if (!hasLocationPermission()) {
+                    continuation.resume(null, null)
+                    return@suspendCancellableCoroutine
+                }
+
+                // 选择合适的位置提供者
+                val providers = mutableListOf<String>().apply {
+                    if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
+                        add(LocationManager.GPS_PROVIDER)
+                    }
+                    if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
+                        add(LocationManager.NETWORK_PROVIDER)
+                    }
+                }
+
+                if (providers.isEmpty()) {
+                    continuation.resume(null, null)
+                    return@suspendCancellableCoroutine
+                }
+
+                // 创建位置监听器
+                locationListener = object : LocationListener {
+                    override fun onLocationChanged(location: Location) {
+                        continuation.resume(location) {
+                            removeLocationUpdates()
+                        }
+                    }
+
+                    override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {}
+                    override fun onProviderEnabled(provider: String) {}
+                    override fun onProviderDisabled(provider: String) {}
+                }
+
+                // 请求位置更新
+                try {
+                    for (provider in providers) {
+                        locationManager.requestLocationUpdates(
+                            provider,
+                            0L,
+                            0f,
+                            locationListener!!,
+                            Looper.getMainLooper()
+                        )
+                    }
+
+                    // 设置超时
+                    launch {
+                        delay(timeoutMillis)
+                        if (!continuation.isCompleted) {
+                            continuation.resume(null) {
+                                removeLocationUpdates()
+                            }
+                        }
+                    }
+                } catch (e: Exception) {
+                    e.printStackTrace()
+                    continuation.resume(null, null)
+                }
+            }
+        }
+
+    // 根据经纬度获取地址
+    suspend fun getAddressFromLocation(latitude: Double, longitude: Double): Address? =
+        withContext(Dispatchers.IO) {
+            try {
+                val addresses: List<Address>? = geocoder.getFromLocation(latitude, longitude, 1)
+                return@withContext addresses?.firstOrNull()
+            } catch (e: IOException) {
+                e.printStackTrace()
+                null
+            }
+        }
+
+    // 移除位置更新监听
+    private fun removeLocationUpdates() {
+        try {
+            locationListener?.let {
+                locationManager.removeUpdates(it)
+                locationListener = null
+            }
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+    }
+
+    // 关闭资源
+    fun close() {
+        removeLocationUpdates()
+    }
+}

+ 0 - 33
app/src/main/java/com/ytpm/hydtw/utils/MainHandler.java

@@ -1,33 +0,0 @@
-package com.ytpm.hydtw.utils;
-
-import android.os.Handler;
-import android.os.Looper;
-
-public class MainHandler {
-
-  private static final Looper mainLooper = Looper.getMainLooper();
-  private static Handler mainHandler;
-
-  private static Handler getMain() {
-    if (mainHandler == null) {
-      mainHandler = new Handler(mainLooper);
-    }
-    return mainHandler;
-  }
-
-  public static boolean postIfNotMain(Runnable r) {
-    if (r == null) {
-      return false;
-    }
-    if (Thread.currentThread() == mainLooper.getThread()) {
-      r.run();
-      return true;
-    } else {
-      return post(r);
-    }
-  }
-
-  public static boolean post(Runnable r) {
-    return getMain().post(r);
-  }
-}

+ 148 - 0
app/src/main/java/com/ytpm/hydtw/utils/PermissionUtils.kt

@@ -0,0 +1,148 @@
+package com.ytpm.hydtw.utils
+
+import android.Manifest
+import android.app.Activity
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.net.Uri
+import android.os.Build
+import android.provider.Settings
+import androidx.appcompat.app.AlertDialog
+import androidx.core.app.ActivityCompat
+import androidx.core.content.ContextCompat
+
+class PermissionUtils(private val context: Context) {
+
+    companion object {
+        const val PERMISSION_REQUEST_CODE = 1001
+
+        val LOCATION_PERMISSIONS = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+            arrayOf(
+                Manifest.permission.ACCESS_FINE_LOCATION,
+                Manifest.permission.ACCESS_COARSE_LOCATION,
+                Manifest.permission.READ_PHONE_STATE,
+                Manifest.permission.READ_SMS
+            )
+        } else {
+            arrayOf(
+                Manifest.permission.ACCESS_FINE_LOCATION,
+                Manifest.permission.ACCESS_COARSE_LOCATION,
+                Manifest.permission.READ_EXTERNAL_STORAGE,
+                Manifest.permission.WRITE_EXTERNAL_STORAGE,
+                Manifest.permission.READ_PHONE_STATE,
+                Manifest.permission.READ_SMS
+            )
+        }
+
+        // 文件存储权限组 (Android 10及以下)
+        val STORAGE_PERMISSIONS_LEGACY = arrayOf(
+            Manifest.permission.READ_EXTERNAL_STORAGE,
+            Manifest.permission.WRITE_EXTERNAL_STORAGE
+        )
+
+        // SIM卡权限
+        val SIM_PERMISSIONS = arrayOf(
+            Manifest.permission.READ_PHONE_STATE
+        )
+    }
+
+    // 检查是否有定位权限
+    fun hasLocationPermission(): Boolean {
+        return LOCATION_PERMISSIONS.all {
+            ContextCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED
+        }
+    }
+
+    // 检查是否有文件存储权限
+    fun hasStoragePermission(): Boolean {
+        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+            // Android 11+ 需要特殊处理
+            Settings.System.canWrite(context)
+        } else {
+            // Android 10及以下使用传统权限
+            STORAGE_PERMISSIONS_LEGACY.all {
+                ContextCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED
+            }
+        }
+    }
+
+    // 检查是否有SIM卡权限
+    fun hasSimPermission(): Boolean {
+        return SIM_PERMISSIONS.all {
+            ContextCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED
+        }
+    }
+
+    // 请求定位权限
+    fun requestLocationPermission(activity: Activity) {
+        ActivityCompat.requestPermissions(
+            activity,
+            LOCATION_PERMISSIONS,
+            PERMISSION_REQUEST_CODE
+        )
+    }
+
+    // 请求文件存储权限
+    fun requestStoragePermission(activity: Activity) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+            // Android 11+ 需要跳转到设置页面
+            val intent = Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION)
+            activity.startActivity(intent)
+        } else {
+            // Android 10及以下使用传统权限请求
+            ActivityCompat.requestPermissions(
+                activity,
+                STORAGE_PERMISSIONS_LEGACY,
+                PERMISSION_REQUEST_CODE
+            )
+        }
+    }
+
+    // 请求SIM卡权限
+    fun requestSimPermission(activity: Activity) {
+        ActivityCompat.requestPermissions(
+            activity,
+            SIM_PERMISSIONS,
+            PERMISSION_REQUEST_CODE
+        )
+    }
+
+    // 检查是否应该显示权限解释对话框
+    fun shouldShowRequestPermissionRationale(activity: Activity, permission: String): Boolean {
+        return ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)
+    }
+
+    // 显示权限解释对话框
+    fun showPermissionExplanationDialog(
+        activity: Activity,
+        title: String,
+        message: String,
+        permissions: Array<String>
+    ) {
+        AlertDialog.Builder(context)
+            .setTitle(title)
+            .setMessage(message)
+            .setPositiveButton("确定") { _, _ ->
+                ActivityCompat.requestPermissions(
+                    activity,
+                    permissions,
+                    PERMISSION_REQUEST_CODE
+                )
+            }
+            .setNegativeButton("取消") { _, _ ->
+                activity.finish()
+            }
+            .show()
+    }
+
+    // 跳转到应用设置页面
+    fun goToAppSettings(activity: Activity) {
+        val intent = Intent(
+            Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
+            Uri.fromParts("package", activity.packageName, null)
+        )
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+        activity.startActivity(intent)
+    }
+}

+ 8 - 6
app/src/main/res/layout/fragment_dati.xml

@@ -5,12 +5,6 @@
     android:layout_height="match_parent"
     android:orientation="vertical">
 
-    <FrameLayout
-        android:id="@+id/fragment_dati_banner"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="30dp"
-        android:background="@color/white" />
 
     <LinearLayout
         android:id="@+id/top"
@@ -772,6 +766,14 @@
         </RelativeLayout>
     </LinearLayout>
 
+    <FrameLayout
+        android:id="@+id/fragment_dati_banner"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="30dp"
+        android:background="@color/white" />
+
+
     <com.anythink.nativead.api.ATNativeAdView
         android:id="@+id/fragment_dati_content_ad"
         android:layout_width="match_parent"

+ 6 - 0
build.gradle.kts

@@ -1,4 +1,10 @@
 plugins {
     alias(libs.plugins.android.application) apply false
     alias(libs.plugins.kotlin.android) apply false
+}
+buildscript {
+
+    dependencies {
+//        classpath("com.pangle.cn:mediation-auto-adapter:1.0.3")
+    }
 }

+ 4 - 3
gradle/libs.versions.toml

@@ -10,7 +10,7 @@ lifecycleRuntimeKtx = "2.6.1"
 appcompat = "1.7.1"
 autosize = "v1.2.1"
 multidex = "2.0.1"
-retrofit = "2.0.2"
+retrofit = "2.9.0"
 utilcodex = "1.31.1"
 glide = "4.16.0"
 immersionbar = "3.2.2"
@@ -19,14 +19,15 @@ wechatSdkAndroidWithoutMta = "6.7.0"
 
 [libraries]
 adapter-rxjava = { module = "com.squareup.retrofit2:adapter-rxjava", version.ref = "retrofit" }
+converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofit" }
+retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
+
 androidx-immersionbar = { group = "com.geyifeng.immersionbar", name = "immersionbar", version.ref = "immersionbar" }
 androidx-immersionbar-ktx = { group = "com.geyifeng.immersionbar", name = "immersionbar-ktx", version.ref = "immersionbar" }
 android-material = { group = "com.google.android.material", name = "material", version.ref = "material" }
-converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofit" }
 glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide" }
 androidx-multidex = { module = "androidx.multidex:multidex", version.ref = "multidex" }
 gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
-retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
 utilcodex = { group = "com.blankj", name = "utilcodex", version.ref = "utilcodex" }
 autosize = { group = "com.github.JessYanCoding", name = "AndroidAutoSize", version.ref = "autosize" }
 androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }

+ 13 - 0
settings.gradle.kts

@@ -9,6 +9,15 @@ pluginManagement {
         }
         mavenCentral()
         gradlePluginPortal()
+
+        //Csj
+        maven {
+            url = uri("https://artifact.bytedance.com/repository/pangle")
+        }
+
+        maven {
+            url = uri("https://maven.byted.org/repository/android_public/")
+        }
     }
 }
 dependencyResolutionManagement {
@@ -32,6 +41,10 @@ dependencyResolutionManagement {
         maven {
             url = uri("https://artifact.bytedance.com/repository/pangle")
         }
+
+        maven {
+            url = uri("https://maven.byted.org/repository/android_public/")
+        }
     }
 }
 

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä