1.1
tj
2025-04-09 2b446a5fd5d8f9b8c0f1e3acef1eef7ad9adb6f9
1.1
已删除13个文件
已修改19个文件
已重命名3个文件
已添加12个文件
1069 ■■■■ 文件已修改
.gitignore 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.idea/.gitignore 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.idea/codeStyles/Project.xml 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.idea/codeStyles/codeStyleConfig.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.idea/compiler.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.idea/deploymentTargetSelector.xml 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.idea/gradle.xml 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.idea/kotlinc.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.idea/migrations.xml 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.idea/misc.xml 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.idea/runConfigurations.xml 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.idea/vcs.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
README.md 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/build.gradle 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/AndroidManifest.xml 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/activity/LoginActivity.kt 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/activity/SettingActivity.kt 141 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/activity/VipActivity.kt 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/database/service/ApiService.kt 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/pay/PayAbility.kt 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/pay/alipay/AliPayHelper.kt 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/pay/alipay/PayAbility.kt 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/pay/alipay/PayResult.kt 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/pay/wxpay/WXPayEntryActivity.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/pay/wxpay/WxPayHelper.kt 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/ui/notifications/NotificationsFragment.kt 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/ui/profile/EditProfileActivity.kt 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/ui/vip/MemberInfoCardFragment.kt 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/utils/AppGlobals.kt 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/layout/activity_setting.xml 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/layout/activity_wxpay_entry.xml 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/layout/fragment_member_info_card.xml 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/layout/fragment_notifications.xml 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/layout/login_protocol_dialog_custom.xml 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/mipmap/setting.png 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/navigation/nav_graph2.xml 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/values-night/themes.xml 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/values-v23/themes.xml 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/values/colors.xml 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/values/strings.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/values/styles.xml 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/values/themes.xml 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
gradle.properties 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
gradle/libs.versions.toml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
keystore/keystore.jks 补丁 | 查看 | 原始文档 | blame | 历史
keystore/sms-manager.jks 补丁 | 查看 | 原始文档 | blame | 历史
keytool 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
@@ -16,3 +16,5 @@
.externalNativeBuild
.cxx
local.properties
.idea/
.idea/.gitignore
文件已删除
.idea/codeStyles/Project.xml
文件已删除
.idea/codeStyles/codeStyleConfig.xml
文件已删除
.idea/compiler.xml
文件已删除
.idea/deploymentTargetSelector.xml
文件已删除
.idea/gradle.xml
文件已删除
.idea/kotlinc.xml
文件已删除
.idea/migrations.xml
文件已删除
.idea/misc.xml
文件已删除
.idea/runConfigurations.xml
文件已删除
.idea/vcs.xml
文件已删除
README.md
@@ -1,6 +1,9 @@
## FirstApp2
短信平台
# 短信平台
# 密码
# md5
ADC67C7C8E0BE3829D34E976D8EFCC9B
app/build.gradle
@@ -14,7 +14,8 @@
    compileSdk 34
    defaultConfig {
        applicationId "com.example.firstapp"
//        applicationId "com.example.firstapp"
        applicationId "net.sourceforge.simcpux"
        minSdk 24
        targetSdk 34
        versionCode 1
@@ -27,7 +28,15 @@
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.debug
        }
        debug {
            minifyEnabled false
            debuggable true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.debug
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
@@ -109,6 +118,23 @@
            excludes += ["META-INF/*.kotlin_module", "META-INF/*.version", "kotlin/**", "DebugProbesKt.bin"]
        }
    }
    signingConfigs {
        release {
            storeFile file('../keystore/sms-manager.jks')
            storePassword 'Cloudroam!@#123'
            keyAlias 'sm'
            keyPassword 'Cloudroam!@#123'
        }
        debug {
            storeFile file('../keystore/keystore.jks')
            storePassword 'android'
            keyAlias 'android'
        }
    }
}
dependencies {
@@ -123,6 +149,7 @@
    implementation libs.androidx.navigation.ui.ktx
    implementation libs.androidx.legacy.support.v4
    implementation libs.androidx.recyclerview
    implementation libs.androidx.activity
    testImplementation libs.junit
    androidTestImplementation libs.androidx.junit
    androidTestImplementation libs.androidx.espresso.core
@@ -294,4 +321,7 @@
    implementation 'de.hdodenhof:circleimageview:3.1.0'
    implementation 'com.github.castorflex:SmoothProgressBar:1.1.0'
    api 'com.tencent.mm.opensdk:wechat-sdk-android:+'
}
app/src/main/AndroidManifest.xml
@@ -83,16 +83,29 @@
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.FirstApp"
        tools:targetApi="31"
        android:usesCleartextTraffic="true"
        >
        tools:targetApi="31">
        <activity
            android:name=".activity.SettingActivity"
            android:configChanges="orientation|keyboardHidden|screenSize"
            android:exported="false"
            android:label="@string/title_activity_setting"
            android:theme="@style/Theme.FirstApp.Fullscreen" />
        <activity
            android:name=".pay.wxpay.WXPayEntryActivity"
            android:exported="true"
            android:launchMode="singleTop" /> <!-- 微信支付回调组件别名 -->
        <activity-alias
            android:name="${applicationId}.wxapi.WXPayEntryActivity"
            android:exported="true"
            android:targetActivity=".pay.wxpay.WXPayEntryActivity"
            android:theme="@android:style/Theme.NoDisplay" />
        <provider
            android:name="androidx.startup.InitializationProvider"
            android:authorities="${applicationId}.androidx-startup"
            android:exported="false"
            tools:node="remove" />
        <activity
            android:name=".activity.VipActivity"
@@ -127,11 +140,10 @@
            android:theme="@style/Theme.ContentDetail" />
        <activity
            android:name=".ui.profile.EditProfileActivity"
            android:exported="false"/>
            android:exported="false" />
        <activity
            android:name=".ui.invitation.InvitationActivity"
            android:exported="false"/>
            android:exported="false" />
    </application>
</manifest>
app/src/main/java/com/example/firstapp/activity/LoginActivity.kt
@@ -1,9 +1,24 @@
package com.example.firstapp.activity
import android.app.AlertDialog
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import android.content.Intent
import android.graphics.Color
import android.text.SpannableString
import android.text.Spanned
import android.text.TextPaint
import android.text.method.LinkMovementMethod
import android.text.style.ClickableSpan
import android.view.LayoutInflater
import android.view.View
import android.widget.Button
import android.widget.CheckBox
import android.widget.TextView
import com.example.firstapp.R
import com.example.firstapp.databinding.ActivityLoginBinding
import com.example.firstapp.utils.PreferencesManager
import kotlin.system.exitProcess
class LoginActivity : AppCompatActivity() {
    private lateinit var binding: ActivityLoginBinding
@@ -13,6 +28,12 @@
        binding = ActivityLoginBinding.inflate(layoutInflater)
        setContentView(binding.root)
        setupViews()
        val phone=PreferencesManager.getLastLoginPhone()
        // 如果phone不存在则展示弹框
        if (phone.isNullOrEmpty()) {
            showConfirmDialog()
        }
    }
    private fun setupViews() {
@@ -41,4 +62,99 @@
        }
    }
    private fun showConfirmDialog() {
        val dialogView = LayoutInflater.from(this).inflate(R.layout.login_protocol_dialog_custom, null)
        val dialog = AlertDialog.Builder(this)
            .setView(dialogView)
            .create()
        dialog.window?.setBackgroundDrawableResource(R.drawable.dialog_background)
        val btnConfirm = dialogView.findViewById<Button>(R.id.btnConfirm)
        btnConfirm.setOnClickListener {
            dialog.dismiss()
        }
        val btnCancel = dialogView.findViewById<Button>(R.id.btnCancel)
        btnCancel.setOnClickListener {
            dialog.dismiss()
            // 退出整个应用
            finishAffinity() // 关闭当前Activity和它之上的所有Activity
            exitProcess(0)   // 终止应用进程(需要引入 kotlin.system.exitProcess)
        }
        // 👇 设置可点击文字逻辑
        val textView = dialogView.findViewById<TextView>(R.id.dialogMessage2)
        val content = "您可以阅读「服务使用协议」和「隐私保护政策」了解相关信息。如果您同意,请点击同意,开始使用我们的服务。"
        val spannableString = SpannableString(content)
        val serviceStart = content.indexOf("「服务使用协议」")
        val serviceEnd = serviceStart + "「服务使用协议」".length
        val privacyStart = content.indexOf("「隐私保护政策」")
        val privacyEnd = privacyStart + "「隐私保护政策」".length
        spannableString.setSpan(object : ClickableSpan() {
            override fun onClick(widget: View) {
                startContentActivity("用户协议", "服务使用协议")
//                Toast.makeText(this@LoginActivity, "点击了服务使用协议", Toast.LENGTH_SHORT).show()
                // 可跳转 WebViewActivity 或打开链接
            }
            override fun updateDrawState(ds: TextPaint) {
                super.updateDrawState(ds)
                ds.color = Color.parseColor("#1E88E5")
                ds.isUnderlineText = false
            }
        }, serviceStart, serviceEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
        spannableString.setSpan(object : ClickableSpan() {
            override fun onClick(widget: View) {
                startContentActivity("隐私协议", "隐私保护政策")
//                Toast.makeText(this@LoginActivity, "点击了隐私保护政策", Toast.LENGTH_SHORT).show()
            }
            override fun updateDrawState(ds: TextPaint) {
                super.updateDrawState(ds)
                ds.color = Color.parseColor("#1E88E5")
                ds.isUnderlineText = false
            }
        }, privacyStart, privacyEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
        textView.text = spannableString
        textView.movementMethod = LinkMovementMethod.getInstance()
        dialog.show()
    }
    /*    private fun showConfirmDialog() {
            val dialogView = LayoutInflater.from(this).inflate(R.layout.login_protocol_dialog_custom, null)
            val dialog = AlertDialog.Builder(this)
                .setView(dialogView)
                .create()
            // 设置自定义背景
            dialog.window?.setBackgroundDrawableResource(R.drawable.dialog_background)
            // 获取按钮并设置点击事件
            val btnConfirm = dialogView.findViewById<Button>(R.id.btnConfirm)
            btnConfirm.setOnClickListener {
                // 将协议勾选上
                dialog.dismiss()
            }
            // 显示对话框
            dialog.show()
        }*/
    private fun startContentActivity(id: String, title: String) {
        val intent = Intent(this, ContentDetailActivity::class.java).apply {
            putExtra(ContentDetailActivity.ID, id)
            putExtra(ContentDetailActivity.EXTRA_TITLE, title)
        }
        startActivity(intent)
    }
}
app/src/main/java/com/example/firstapp/activity/SettingActivity.kt
对比新文件
@@ -0,0 +1,141 @@
package com.example.firstapp.activity
import androidx.appcompat.app.AppCompatActivity
import android.annotation.SuppressLint
import android.app.AlertDialog
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.Gravity
import android.view.MenuItem
import android.view.MotionEvent
import android.view.View
import android.view.WindowInsets
import android.widget.LinearLayout
import android.widget.TextView
import androidx.appcompat.widget.Toolbar
import androidx.lifecycle.ViewModelProvider
import com.example.firstapp.databinding.ActivitySettingBinding
import com.example.firstapp.R
import com.example.firstapp.ui.home.HomeViewModel
/**
 * An example full-screen activity that shows and hides the system UI (i.e.
 * status bar and navigation/system bar) with user interaction.
 */
class SettingActivity : AppCompatActivity() {
    private lateinit var binding: ActivitySettingBinding
    private val homeViewModel: HomeViewModel by lazy {
        ViewModelProvider(this).get(HomeViewModel::class.java)
    }
    private var isFullscreen: Boolean = false
    @SuppressLint("ClickableViewAccessibility")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivitySettingBinding.inflate(layoutInflater)
        setContentView(binding.root)
        var toolbar=binding.settingToolbar
        // 获取 Toolbar 并设置为 ActionBar
        setSupportActionBar(toolbar)
        // 显示返回按钮
        supportActionBar?.setDisplayHomeAsUpEnabled(true)
        supportActionBar?.setDisplayShowHomeEnabled(true)
        // 设置标题(如果没有在 XML 中设置标题,可以在代码中动态设置)
        supportActionBar?.title = ""
//        binding.settingExit.setOnClickListener(View.OnClickListener {
//
//            homeViewModel.logout()
//            // 跳转到vipActivity
//            val intent = Intent(this, LoginActivity::class.java)
//            intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
//            startActivity(intent)
//
//        })
        binding.settingExit.setOnClickListener {
            // 弹出确认退出的对话框
            val alertDialog = AlertDialog.Builder(this)
                .setTitle("确认退出")
                .setMessage("您确定要退出吗?")
                .setPositiveButton("确认") { dialog, _ ->
                    // 确认退出
                    homeViewModel.logout()
                    // 跳转到 LoginActivity 并清除之前的任务栈
                    val intent = Intent(this, LoginActivity::class.java)
                    intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
                    startActivity(intent)
                    // 关闭当前页面
                    finish()
                }
                .setNegativeButton("取消") { dialog, _ ->
                    // 取消退出操作
                    dialog.dismiss()
                }
                .create()
            // 显示对话框
            alertDialog.show()
        }
    }
    // 点击返回按钮时调用
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        if (item.itemId == android.R.id.home) {
            onBackPressed()
            return true
        }
        return super.onOptionsItemSelected(item)
    }
    override fun onPostCreate(savedInstanceState: Bundle?) {
        super.onPostCreate(savedInstanceState)
        // Trigger the initial hide() shortly after the activity has been
        // created, to briefly hint to the user that UI controls
        // are available.
        delayedHide(100)
    }
    private fun toggle() {
        if (isFullscreen) {
            hide()
        } else {
            show()
        }
    }
    private fun hide() {
        // Hide UI first
        supportActionBar?.hide()
    }
    private fun show() {
    }
    private fun delayedHide(delayMillis: Int) {
    }
}
app/src/main/java/com/example/firstapp/activity/VipActivity.kt
@@ -252,8 +252,9 @@
                        Toast.makeText(this@VipActivity, "请勾选协议", Toast.LENGTH_LONG).show()
                        return@launch // 直接 return,不往下执行
                    }
                    Toast.makeText(this@VipActivity, "功能暂未开放", Toast.LENGTH_LONG).show()
                    return@launch
//                    Toast.makeText(this@VipActivity, "功能暂未开放", Toast.LENGTH_LONG).show()
//                    return@launch
                    doWechatPay()
                } catch (e: Exception) {
@@ -266,6 +267,23 @@
    }
    private fun doWechatPay() {
        val map=HashMap<String,String>()
        map["appId"]="wxb4ba3c02aa476ea1"
        map["partnerid"]="1900006771"
        map["package"]="Sign=WXPay"
        map["noncestr"]="2ac6c60ebfe7e549fbbc922ac54269bb"
        map["timeStamp"]="1606317975"
        map["prepayid"]="wx25232614962974fb29d1227819cc3e000g"
        map["sign"]="wx25232614962974fb29d1227819cc3e000g"
        PayAbility.wxPay(this, map, Observer { success ->
            if (success == 0) {
                Toast.makeText(this@VipActivity, "支付失败", Toast.LENGTH_LONG).show()
            } else {
                Toast.makeText(this@VipActivity, "支付成功", Toast.LENGTH_LONG).show()
            }
        })
    }
    private fun vipCardInit() {
        val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)
app/src/main/java/com/example/firstapp/database/service/ApiService.kt
@@ -62,7 +62,7 @@
    suspend fun getUserInfo(@Path("phone") phone: String): ApiResponse<UserInfo>
    @Multipart
    @POST("flower/api/supplier/operation/update")
    @POST("api/supplier/operation/update")
    suspend fun updateProfile(
        @Part("nickname") nickname: RequestBody,
        @Part avatar: MultipartBody.Part?
@@ -78,8 +78,8 @@
// 创建Retrofit实例(单例)
object RetrofitClient{
//    private const val BASE_URL ="http://192.168.1.198:8080/flower/"
    private const val BASE_URL ="http://14.103.144.28:8080/flower/"
    private const val BASE_URL ="http://192.168.1.198:8080/flower/"
//    private const val BASE_URL ="http://14.103.144.28:8080/flower/"
    // 创建OkHttpClient,配置拦截器和超时时间
app/src/main/java/com/example/firstapp/pay/PayAbility.kt
文件已删除
app/src/main/java/com/example/firstapp/pay/alipay/AliPayHelper.kt
app/src/main/java/com/example/firstapp/pay/alipay/PayAbility.kt
对比新文件
@@ -0,0 +1,35 @@
package com.example.firstapp.pay
import android.app.Activity
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
object PayAbility {
    private val wxPayResultLiveData = MutableLiveData<Int?>()
    /**
     * 支付宝支付方法
     */
    fun aliPay(activity: Activity, orderInfo: String, observer: Observer<PayResult>) {
        AliPayHelper.pay(activity, orderInfo, observer)
    }
    /**
     * 微信支付方法
     */
    fun wxPay(activity: Activity, orderInfo: Map<String,String>, observer: Observer<Int?>) {
        if(activity is FragmentActivity){
            wxPayResultLiveData.observe(activity, observer)
        }
        WxPayHelper.pay(activity, orderInfo, observer)
    }
    internal fun postWXPayResult(result: Int) {
        wxPayResultLiveData.postValue(result)
        wxPayResultLiveData.value= null
    }
}
app/src/main/java/com/example/firstapp/pay/alipay/PayResult.kt
app/src/main/java/com/example/firstapp/pay/wxpay/WXPayEntryActivity.java
对比新文件
@@ -0,0 +1,44 @@
package com.example.firstapp.pay.wxpay;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import com.tencent.mm.opensdk.constants.ConstantsAPI;
import com.tencent.mm.opensdk.modelbase.BaseReq;
import com.tencent.mm.opensdk.modelbase.BaseResp;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {
    private static final String TAG = "WXPayEntryActivity";
    private IWXAPI api;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
       getWindow().setBackgroundDrawable(null);
       super.onCreate(savedInstanceState);
        api= WXAPIFactory.createWXAPI(this,"wxb4ba302aa476ea1");
        api.handleIntent(getIntent(),this);
    }
    @Override
    public void onReq(BaseReq baseReq) {
    }
    @Override
    public void onResp(BaseResp baseResp) {
        Log.d(TAG,"onPayFinish,errCode="+baseResp.errCode);
        if(baseResp.getType()== ConstantsAPI.COMMAND_PAY_BY_WX){
            finish();
        }
    }
}
app/src/main/java/com/example/firstapp/pay/wxpay/WxPayHelper.kt
对比新文件
@@ -0,0 +1,42 @@
package com.example.firstapp.pay
import android.app.Activity
import android.text.TextUtils
import androidx.lifecycle.Observer
import com.alipay.sdk.app.PayTask
import com.example.firstapp.utils.AppGlobals
import com.example.firstapp.utils.Log
import com.tencent.mm.opensdk.modelpay.PayReq
import com.tencent.mm.opensdk.openapi.WXAPIFactory
object WxPayHelper {
    private val api=WXAPIFactory.createWXAPI(AppGlobals.get(), "wx4f794c0f0f0f0f0f",true)
    init {
        api.registerApp("wx4f794c0f0f0f0f0f")
    }
    fun pay(activity: Activity, params:Map<String,String>,observer:Observer<Int?>) {
        // 开启线程
        Thread {
            try {
                val req=PayReq()
                req.appId=params["appid"]
                req.partnerId=params["partnerid"]
                req.prepayId=params["prepayid"]
                req.nonceStr=params["noncestr"]
                req.timeStamp=params["timestamp"]
                req.packageValue=params["package"]
                req.sign=params["sign"]
                req.signType=params["signType"]
                req.extData=params["extData"]
                api.sendReq(req)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }.start()
    }
}
app/src/main/java/com/example/firstapp/ui/notifications/NotificationsFragment.kt
@@ -31,6 +31,7 @@
import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.launch
import com.bumptech.glide.Glide
import com.example.firstapp.activity.SettingActivity
import com.example.firstapp.activity.VipActivity
import com.example.firstapp.database.response.UserInfo
import com.example.firstapp.ui.invitation.InvitationActivity
@@ -95,6 +96,14 @@
        }
        return binding.root
    }
    override fun onResume() {
        super.onResume()
        // 加载用户信息
        lifecycleScope.launch {
            loadUserInfo()
        }
    }
    private suspend fun loadConfigurations() {
@@ -217,6 +226,13 @@
            startActivity(intent)
        }
        // 设置按钮点击
        binding.ivSetting.setOnClickListener {
            // 跳转到
            val intent = Intent(requireContext(), SettingActivity::class.java)
            startActivity(intent)
        }
    }
app/src/main/java/com/example/firstapp/ui/profile/EditProfileActivity.kt
@@ -18,8 +18,11 @@
import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope
import com.bumptech.glide.Glide
import com.example.firstapp.database.response.UserInfo
import com.example.firstapp.databinding.ActivityEditProfileBinding
import com.example.firstapp.database.service.ApiService
import com.example.firstapp.database.service.RetrofitClient
import com.example.firstapp.utils.PreferencesManager
import kotlinx.coroutines.launch
import java.io.File
import okhttp3.MediaType.Companion.toMediaType
@@ -31,7 +34,6 @@
class EditProfileActivity : AppCompatActivity() {
    private lateinit var binding: ActivityEditProfileBinding
    private var selectedImageUri: Uri? = null
    private lateinit var apiService: ApiService
    private var loadingDialog: AlertDialog? = null
    private val pickImage = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
@@ -114,12 +116,38 @@
                }
                // 调用更新接口
                apiService.updateProfile(
                RetrofitClient.apiService.updateProfile(
                    nickname = nicknameBody,
                    avatar = avatarPart
                )
                Toast.makeText(this@EditProfileActivity, "保存成功", Toast.LENGTH_SHORT).show()
                // 更新用户信息
                // 从本地获取保存的手机号
                val savedPhone = PreferencesManager.getPhone()
                if (savedPhone.isNullOrEmpty()) {
                    Toast.makeText(this@EditProfileActivity, "用户未登录", Toast.LENGTH_SHORT).show()
                    return@launch
                }
                val response = RetrofitClient.apiService.getUserInfo(savedPhone)
                if (response.code == "0" && response.data != null) {
                    // 保存用户信息
                    val userInfo:UserInfo = response.data
                    // 获取传入的数据
                    val currentNickname = userInfo.name
                    val currentAvatarUrl = userInfo.cover
                    // 设置当前数据
                    binding.etNickname.setText(currentNickname)
                    if (!currentAvatarUrl.isNullOrEmpty()) {
                        Glide.with(this@EditProfileActivity)
                            .load(currentAvatarUrl)
                            .circleCrop()
                            .into(binding.ivAvatar)
                    }
                }
                finish()
            } catch (e: Exception) {
app/src/main/java/com/example/firstapp/ui/vip/MemberInfoCardFragment.kt
@@ -53,6 +53,7 @@
        Glide.with(this)
            .load(viewModel.cover)
            .circleCrop()
            .transform(RoundedCorners(100))  // 设置圆角
//            .error(R.drawable.error_placeholder) // 如果加载失败,显示占位图
            .error(R.mipmap.avatar_default)
@@ -118,6 +119,7 @@
            viewModel.cover.collect { coverUrl ->
                Glide.with(this@MemberInfoCardFragment)
                    .load(coverUrl)
                    .circleCrop()
                    .transform(RoundedCorners(100))
                    .error(R.drawable.error_placeholder)
                    .into(binding.memberAvatarView)
@@ -132,6 +134,7 @@
                    .transform(RoundedCorners(100))
                    .error(R.drawable.error_placeholder)
                    .into(binding.memberImageView)
            }
        }
app/src/main/java/com/example/firstapp/utils/AppGlobals.kt
对比新文件
@@ -0,0 +1,29 @@
package com.example.firstapp.utils
import android.app.Application
import java.lang.Exception
/**
 * 这种方式获取全局的Application 是一种拓展思路。
 *
 *
 * 对于组件化项目,不可能把项目实际的Application下沉到Base,而且各个module也不需要知道Application真实名字
 *
 *
 * 这种一次反射就能获取全局Application对象的方式相比于在Application#OnCreate保存一份的方式显示更加通用了
 */
object AppGlobals {
    private var application: Application? = null
    fun get(): Application? {
        if (application == null) {
            try {
                application = Class.forName("android.app.ActivityThread")
                    .getMethod("currentApplication")
                    .invoke(null) as Application
            } catch (ex: Exception) {
                ex.printStackTrace()
            }
        }
        return application
    }
}
app/src/main/res/layout/activity_setting.xml
对比新文件
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#F0F2F5"
    tools:context=".activity.SettingActivity">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <!-- Toolbar (标题栏) -->
        <androidx.appcompat.widget.Toolbar
            android:id="@+id/setting_toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#F9F9F9"
            android:elevation="4dp"
            android:layout_gravity="center"
            android:gravity="center">
            <!-- 自定义标题 TextView -->
            <TextView
                android:id="@+id/toolbar_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="设置"
                android:textColor="@android:color/black"
                android:textSize="18sp"
                android:layout_gravity="center"
                android:gravity="center" /> <!-- 确保标题居中 -->
        </androidx.appcompat.widget.Toolbar>
        <LinearLayout
            android:id="@+id/setting_exit"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:gravity="center"
            android:orientation="vertical"
            android:background="#F9F9F9"
            android:layout_marginTop="20dp"
            >
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="5dp"
                android:text="退出登录"
                android:textColor="#E23C2F" />
        </LinearLayout>
    </LinearLayout>
</FrameLayout>
app/src/main/res/layout/activity_wxpay_entry.xml
对比新文件
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".pay.wxpay.WXPayEntryActivity">
</androidx.constraintlayout.widget.ConstraintLayout>
app/src/main/res/layout/fragment_member_info_card.xml
@@ -36,15 +36,26 @@
                android:background="@android:color/transparent"
                >
                <ImageView
<!--                <ImageView-->
<!--                    android:id="@+id/memberAvatarView"-->
<!--                    android:layout_width="25dp"-->
<!--                    android:layout_height="27dp"-->
<!--                    android:layout_marginLeft="10dp"-->
<!--                    android:scaleType="centerCrop"-->
<!--                    app:layout_constraintStart_toStartOf="parent"-->
<!--                    app:layout_constraintTop_toTopOf="parent"-->
<!--                    />-->
                <com.google.android.material.imageview.ShapeableImageView
                    android:id="@+id/memberAvatarView"
                    android:layout_width="40dp"
                    android:layout_height="40dp"
                    android:layout_marginLeft="10dp"
                    android:layout_marginRight="10dp"
                    android:scaleType="centerCrop"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="parent" />
                    app:layout_constraintTop_toTopOf="parent"
                    app:shapeAppearanceOverlay="@style/CircleImageView" />
                <TextView
                    android:id="@+id/phoneNumberText"
app/src/main/res/layout/fragment_notifications.xml
@@ -19,6 +19,27 @@
            android:layout_height="32dp"
            android:scaleType="centerCrop" />
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="25dp"
            android:gravity="center_vertical"
            android:orientation="horizontal">
            <View
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1" />
            <ImageView
                android:id="@+id/iv_setting"
                android:layout_width="28dp"
                android:layout_height="wrap_content"
                android:layout_marginEnd="8dp"
                android:contentDescription="设置"
                android:src="@mipmap/setting" />
        </LinearLayout>
        <!-- 用户信息区域 - 减小padding -->
        <RelativeLayout
            android:id="@+id/layout_user_info"
app/src/main/res/layout/login_protocol_dialog_custom.xml
对比新文件
@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:background="@drawable/dialog_background"
    android:padding="20dp"
    android:gravity="center"
    >
    <!-- 标题 -->
    <TextView
        android:id="@+id/dialogTitle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="服务协议和隐私政策"
        android:textSize="20sp"
        android:textColor="#000000"
        android:gravity="center"
        android:paddingBottom="10dp" />
    <View
        android:id="@+id/divider"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#E2E2E2"
        android:layout_marginTop="5dp"
        android:layout_marginHorizontal="0dp" />
    <!-- 内容 -->
    <TextView
        android:id="@+id/dialogMessage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="请您务必阅读、理解「服务协议】和「隐私政策」,我们仅会收集提供服务必要的信息:未经您同意,我们不会与第三方共享与披露您的个人隐私信息。"
        android:textSize="16sp"
        android:textColor="#000000"
        android:gravity="left"
        android:layout_marginTop="5dp"
        android:paddingBottom="20dp" />
    <TextView
        android:id="@+id/dialogMessage2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="您可以阅读「服务使用协议」和「隐私保护政策」了解相关信息。如果您同意,请点击「同意,开始使用我们的服务。"
        android:textSize="16sp"
        android:textColor="#000000"
        android:gravity="left"
        android:paddingBottom="20dp" />
    <!-- 按钮 -->
    <Button
        android:id="@+id/btnConfirm"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:text="同意"
        android:textColor="@android:color/white"
        android:backgroundTint="#000000"
        android:gravity="center" />
<!--    <Button-->
<!--        android:id="@+id/btnCancel"-->
<!--        android:layout_width="200dp"-->
<!--        android:layout_height="wrap_content"-->
<!--        android:text="不同意"-->
<!--        android:textColor="@android:color/white"-->
<!--        android:backgroundTint="#000000"-->
<!--        android:gravity="center" />-->
    <Button
        android:id="@+id/btnCancel"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:text="不同意"
        android:textColor="#999999"
        android:background="@android:color/transparent"
        android:gravity="center"
        android:elevation="0dp"
        android:stateListAnimator="@null" />
</LinearLayout>
app/src/main/res/mipmap/setting.png
app/src/main/res/navigation/nav_graph2.xml
对比新文件
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_graph2"
    app:startDestination="@id/First2Fragment">
    <fragment
        android:id="@+id/First2Fragment"
        android:name="com.example.firstapp.pay.wxpay.First2Fragment"
        android:label="@string/first_fragment_label"
        tools:layout="@layout/fragment_first2">
        <action
            android:id="@+id/action_First2Fragment_to_Second2Fragment"
            app:destination="@id/Second2Fragment" />
    </fragment>
    <fragment
        android:id="@+id/Second2Fragment"
        android:name="com.example.firstapp.pay.wxpay.Second2Fragment"
        android:label="@string/second_fragment_label"
        tools:layout="@layout/fragment_second2">
        <action
            android:id="@+id/action_Second2Fragment_to_First2Fragment"
            app:destination="@id/First2Fragment" />
    </fragment>
</navigation>
app/src/main/res/values-night/themes.xml
对比新文件
@@ -0,0 +1,12 @@
<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Base.Theme.FirstApp" parent="Theme.Material3.DayNight.NoActionBar">
        <!-- Customize your dark theme here. -->
        <!-- <item name="colorPrimary">@color/my_dark_primary</item> -->
    </style>
    <style name="ThemeOverlay.FirstApp.FullscreenContainer" parent="">
        <item name="fullscreenBackgroundColor">@color/light_blue_900</item>
        <item name="fullscreenTextColor">@color/light_blue_A400</item>
    </style>
</resources>
app/src/main/res/values-v23/themes.xml
@@ -1,9 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!--    <style name="Theme.FirstApp" parent="Base.Theme.FirstApp">-->
<!--        &lt;!&ndash; Transparent system bars for edge-to-edge. &ndash;&gt;-->
<!--        <item name="android:navigationBarColor">@android:color/transparent</item>-->
<!--        <item name="android:statusBarColor">@android:color/transparent</item>-->
<!--        <item name="android:windowLightStatusBar">?attr/isLightTheme</item>-->
<!--    </style>-->
    <!--    <style name="Theme.FirstApp" parent="Base.Theme.FirstApp">-->
    <!--        &lt;!&ndash; Transparent system bars for edge-to-edge. &ndash;&gt;-->
    <!--        <item name="android:navigationBarColor">@android:color/transparent</item>-->
    <!--        <item name="android:statusBarColor">@android:color/transparent</item>-->
    <!--        <item name="android:windowLightStatusBar">?attr/isLightTheme</item>-->
    <!--    </style>-->
    <style name="Theme.FirstApp" parent="Base.Theme.FirstApp">
        <!-- Transparent system bars for edge-to-edge. -->
        <item name="android:navigationBarColor">@android:color/transparent</item>
        <item name="android:statusBarColor">@android:color/transparent</item>
        <item name="android:windowLightStatusBar">?attr/isLightTheme</item>
    </style>
</resources>
app/src/main/res/values/colors.xml
@@ -16,5 +16,6 @@
    <color name="light_blue_50">#E1F5FE</color>
    <color name="tab_selected">#FF039BE5</color>
    <color name="light_blue_new">#02A7F0</color>
    <color name="light_grey">#F6F7FB </color> 灰色主题
    <color name="light_grey">#F6F7FB</color>
    灰色主题
</resources>
app/src/main/res/values/strings.xml
@@ -94,5 +94,6 @@
    <string name="invite_reward_text"><![CDATA[
    每邀请1位新用户<font color="#FF0000"><b><i><u>可得</u></i></b></font>
]]></string>
    <string name="title_activity_setting">SettingActivity</string>
</resources>
app/src/main/res/values/styles.xml
@@ -55,4 +55,12 @@
        <item name="cornerFamily">rounded</item>
        <item name="cornerSize">50%</item>
    </style>
    <!-- 自定义标题样式 -->
    <style name="ToolbarTitleStyle">
        <item name="android:textSize">18sp</item> <!-- 设置标题字体大小 -->
        <item name="android:gravity">center</item> <!-- 设置标题居中 -->
        <item name="android:textColor">#000000</item> <!-- 设置标题颜色 -->
    </style>
</resources>
app/src/main/res/values/themes.xml
@@ -23,9 +23,9 @@
    </style>
    <style name="Theme.FirstApp.Fullscreen" parent="Theme.FirstApp">
<!--        <item name="android:actionBarStyle">@style/Widget.Theme.FirstApp.ActionBar.Fullscreen</item>-->
<!--        <item name="android:windowActionBarOverlay">true</item>-->
<!--        <item name="android:windowBackground">@null</item>-->
        <!--        <item name="android:actionBarStyle">@style/Widget.Theme.FirstApp.ActionBar.Fullscreen</item>-->
        <!--        <item name="android:windowActionBarOverlay">true</item>-->
        <!--        <item name="android:windowBackground">@null</item>-->
    </style>
    <style name="ThemeOverlay.FirstApp.FullscreenContainer" parent="">
gradle.properties
@@ -35,5 +35,8 @@
android.precompileDependenciesResources=false
android.enableJetifier=true
#android.enableD8=true
org.gradle.java.home=D\:\\tanjiyaun\\jdk\\jdk1.8\\jdk-17.0.12
org.gradle.java.home=D\:\\devInstall\\java\\jdk-17.0.12
# ??????
WX_PAY_APP_ID=wxb4ba302aa476ea1
gradle/libs.versions.toml
@@ -15,6 +15,7 @@
legacySupportV4 = "1.0.0"
fragmentKtx = "1.5.6"
recyclerview = "1.3.0"
activity = "1.8.0"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
@@ -31,6 +32,7 @@
androidx-legacy-support-v4 = { group = "androidx.legacy", name = "legacy-support-v4", version.ref = "legacySupportV4" }
androidx-fragment-ktx = { group = "androidx.fragment", name = "fragment-ktx", version.ref = "fragmentKtx" }
androidx-recyclerview = { group = "androidx.recyclerview", name = "recyclerview", version.ref = "recyclerview" }
androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
keystore/keystore.jks
Binary files differ
keystore/sms-manager.jks
Binary files differ
keytool