乐于分享
好东西不私藏

安卓游戏《宠物1.0》制作全流程

安卓游戏《宠物1.0》制作全流程
01概述
02部署Gradle(配置API环境)

Gradle 是 Android 官方统一的项目构建工具,你可以把它理解成「安卓项目的自动化管家」。没有它,你的 Kotlin/Java 代码、图片、动画、布局资源无法编译成手机能安装的 APK 安装包。

一般情况下,第一次打开android studio,gradle就会自动部署,但是我的API 24报错了,下载不了官网上的资源包。
将网址换成国内镜像,且注释掉哈希表后还是不行。
然后我换了一个APK版本——API 30。
这个版本的兼容性不及API24好,但是我的手机也能运行。
还是不行:

DNS 解析失败,Android Studio 无法解析 Gradle 插件仓库域名,国内网络无法直连谷歌 / Gradle 官方插件源,域名找不到服务器。

最后换成了兼容性最好的API 23,很顺利,近八分钟就下载完了。
然后:

API 23 是不是最新?

不是,而且不推荐你用 API 23

API 23 = Android 6.0,发布于 2015 年,非常老旧;

Jetpack Compose(你现在项目用的界面框架)最低兼容要求是 API 21,但 API23 缺少大量现代界面、通知权限相关 API,后续你做「读取手机消息、交互动画」会频繁出现兼容报错;

小米 13 出厂 Android13 (API33),虽然能装 API23 的 App,但高系统权限逻辑和 6.0 完全不一样,适配会很麻烦;

最新正式 Android 版本是 Android15(API35),建议改回 API24(Android7.0),兼顾兼容与功能。

我不管,我先把hello world弄出来再删。
顺利,改三行代码中的输出文本即可。

minSdk=24(Android7.0)能补齐什么

完整支持通知渠道兼容代码,在小米 13 等新手机上通知、提示音 100% 正常弹出;

完善精确闹钟 API setExactAndAllowWhileIdle,大幅降低高系统后台杀定时任务概率;

XML 矢量动画、帧动画全部 API 原生兼容,无渲染 bug;

权限细分更完善,适配安卓 10~14 的后台、定位、通知限制代码更简洁,不需要大量 if 版本判断;

兼容绝大多数现代动画、定时第三方库,不会出现依赖版本冲突

很奇妙的事情发生了,我再次安装一遍24,又能安装了。
这次直接用它原生的,直接输出hello android。

API(Application Programming Interface)应用程序编程接口,一套功能调用规则 / 函数入口,是系统、库对外开放的 “操作按钮”。

SDK(Software Development Kit)软件开发工具包,一整套开发工具合集,里面包含:全部 API 源码文档、编译工具、模拟器、资源工具、系统库文件。

Gradle 项目构建工具,自动化管理工具,负责连接 Android Studio、SDK、第三方库,完成下载、编译、打包全流程。

03改页面背景颜色
bug:已在colors.xml新增darkgreen颜色,同时在MainActivity的页面代码与预览@Preview函数中,均给Scaffold添加background(colorResource(R.color.darkgreen)),刷新 Compose 预览后,页面背景仍保持白色,未变为深绿色。

Scaffold 英文原意:脚手架、支架

在 Jetpack Compose 里:页面标准布局容器,安卓官方给 App 页面封装好的「标准页面骨架」。

04android studio接入DeepSeek api
这是DeepSeek收费标准,我充了10块钱足够我用了。
在官网进入api开放平台,创建一个key,复制密钥后回到android studio。
避坑:在创建settings时选第三方提供者,不要选本地(谷歌)。
填好信息后,apply即可。
在下方选择指定模型。
然后让人啼笑皆非的事情发生了,DeepSeek说自己不是DeepSeek。
没关系,能用就行。
这个模型不支持上传图片,然后我继续问豆包,豆包知道我的问题(改了代码,画面还是纯白),于是给了我代码:
class MainActivity : ComponentActivity() {    override funonCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        enableEdgeToEdge()        setContent {            PetTheme {                // 外层Box铺满屏幕,设置全局绿色背景                Box(                    modifier = Modifier                        .fillMaxSize()                        .background(colorResource(R.color.darkgreen))                ) {                    // Scaffold设置透明,不遮挡外层绿色                    Scaffold(                        modifier = Modifier.fillMaxSize(),                        containerColor = Color.Transparent                    ) { innerPadding ->                        Greeting(                            name = "Android",                            modifier = Modifier.padding(innerPadding)                        )                    }                }            }        }    }}@ComposablefunGreeting(name: String, modifier: Modifier = Modifier) {    Text(        text = "Hello $name!",        modifier = modifier    )}@Preview@ComposablefunGreetingPreview() {    PetTheme {        Box(            modifier = Modifier                .fillMaxSize()                .background(colorResource(R.color.darkgreen))        ) {            Scaffold(                modifier = Modifier.fillMaxSize(),                containerColor = Color.Transparent            ) { innerPadding ->                Greeting("Android", Modifier.padding(innerPadding))            }        }    }}
但是这行代码复制到studio是报错的,然后我用报错行下面的fix with ai,然后很顺利,agent立马帮我修好了,运行正常,主要就是在开头添加import。
我悟了:豆包善于理解需求制定大方向,agent善于修bug,让大方向适配现实。好了,我集齐了卧龙凤雏,未来光明了。
本次消费:
05点击方块跳跃并狗叫
(1)实现点击方块跳跃:
package com.example.petimport android.os.Bundleimport androidx.activity.ComponentActivityimport androidx.activity.compose.setContentimport androidx.activity.enableEdgeToEdgeimport androidx.compose.foundation.backgroundimport androidx.compose.foundation.clickableimport androidx.compose.foundation.layout.Boximport androidx.compose.foundation.layout.fillMaxSizeimport androidx.compose.foundation.layout.paddingimport androidx.compose.foundation.layout.sizeimport androidx.compose.material3.Scaffoldimport androidx.compose.runtime.Composableimport androidx.compose.runtime.getValueimport androidx.compose.runtime.mutableStateOfimport androidx.compose.runtime.rememberimport androidx.compose.runtime.setValueimport androidx.compose.ui.Alignmentimport androidx.compose.ui.Modifierimport androidx.compose.ui.graphics.Colorimport androidx.compose.ui.res.colorResourceimport androidx.compose.ui.tooling.preview.Previewimport androidx.compose.ui.unit.dpimport androidx.compose.ui.unit.Dpimport com.example.pet.ui.theme.PetThemeimport androidx.compose.animation.core.animateDpAsStateimport androidx.compose.animation.core.animateFloatAsStateimport androidx.compose.animation.core.tweenimport androidx.compose.ui.graphics.graphicsLayerclass MainActivity : ComponentActivity() {    override funonCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        enableEdgeToEdge()        setContent {            PetTheme {                // 全局绿色背景外层容器                Box(                    modifier = Modifier                        .fillMaxSize()                        .background(colorResource(id = R.color.darkgreen))                ) {                    Scaffold(                        modifier = Modifier.fillMaxSize(),                        containerColor = Color.Transparent                    ) { innerPadding ->                        // 居中橙色像素小狗组件                        Box(                            modifier = Modifier                                .fillMaxSize()                                .padding(innerPadding),                            contentAlignment = Alignment.Center                        ) {                            PixelDog()                        }                    }                }            }        }    }}/** * 橙色像素小狗 + 点击缩放交互动画 */@Composablefun PixelDog(modifier: Modifier = Modifier) {    // 控制动画触发    var jumpTrigger by remember { mutableStateOf(false) }    // Y轴偏移:向上跳跃100dp    val jumpOffset: Dp by animateDpAsState(        targetValue = if (jumpTrigger) (-200).dp else 0.dp,        animationSpec = tween(durationMillis = 400),        finishedListener = { jumpTrigger = false } // 动画结束复位    )    // 逆时针旋转360度    val rotateAngle: Float by animateFloatAsState(        targetValue = if (jumpTrigger) -360f else 0f,        animationSpec = tween(durationMillis = 400)    )    Box(        modifier = modifier            .size(120.dp)            .clickable { jumpTrigger = true } // 点击触发后空翻            .graphicsLayer {                translationY = jumpOffset.toPx()                rotationZ = rotateAngle            },        contentAlignment = Alignment.Center    ) {        // 橙色像素小狗纯色方块(无图片依赖,直接消除资源报错)        Box(            modifier = Modifier                .size(300.dp)                .background(Color(0xFFfe8862))        )    }}@Preview@Composablefun Preview() {    PetTheme {        Box(            modifier = Modifier                .fillMaxSize()                .background(colorResource(id = R.color.darkgreen))        ) {            Scaffold(                modifier = Modifier.fillMaxSize(),                containerColor = Color.Transparent            ) { innerPadding ->                Box(                    modifier = Modifier                        .fillMaxSize()                        .padding(innerPadding),                    contentAlignment = Alignment.Center                ) {                    PixelDog()                }            }        }    }}
(2)尝试ai生成狗叫:
很多开源的东西都在外网,而这两天网络一直不稳定,为了一劳永逸,我打算解决网络问题。在CSDN上找到一个人推荐的软件Watt Toolkit

https://steampp.net/

非常好用。立刻解决了进入GitHub的问题。

Mac 弹出要开机密码,是因为它需要修改系统网络代理 / Hosts 文件

但是在GitHub和replicate上都没有找合适的可以在线使用的模型。(积累本地部署Suno bark的经验,镜像、资源包都忙活完了,结果最后一运行却差强人意。

https://replicate.com

(3)所以我改为使用线上可商用的音效资源:

https://www.ear0.com

狗叫 许可:CC-BY 作者:noctaro 来源:耳聆网 https://www.ear0.com/sound/13212
(4)实现点击方块狗叫
在res的子集中新建一个文件夹,命名为raw。直接commend+c 储存在本地的wav文件,commend+v raw文件夹,就能实现wav导入安卓studio。
还是用豆包文生代码,用deepseek的API调试。
package com.example.petimport android.media.MediaPlayerimport android.os.Bundleimport androidx.activity.ComponentActivityimport androidx.activity.compose.setContentimport androidx.activity.enableEdgeToEdgeimport androidx.compose.animation.core.animateDpAsStateimport androidx.compose.animation.core.animateFloatAsStateimport androidx.compose.animation.core.tweenimport androidx.compose.foundation.backgroundimport androidx.compose.foundation.clickableimport androidx.compose.foundation.layout.Boximport androidx.compose.foundation.layout.fillMaxSizeimport androidx.compose.foundation.layout.paddingimport androidx.compose.foundation.layout.sizeimport androidx.compose.material3.Scaffoldimport androidx.compose.runtime.Composableimport androidx.compose.runtime.DisposableEffectimport androidx.compose.runtime.getValueimport androidx.compose.runtime.mutableStateOfimport androidx.compose.runtime.rememberimport androidx.compose.runtime.setValueimport androidx.compose.ui.Alignmentimport androidx.compose.ui.Modifierimport androidx.compose.ui.graphics.Colorimport androidx.compose.ui.graphics.graphicsLayerimport androidx.compose.ui.platform.LocalContextimport androidx.compose.ui.res.colorResourceimport androidx.compose.ui.tooling.preview.Previewimport androidx.compose.ui.unit.Dpimport androidx.compose.ui.unit.dpimport com.example.pet.ui.theme.PetThemeclass MainActivity : ComponentActivity() {    override funonCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        enableEdgeToEdge()        setContent {            PetTheme {                Box(                    modifier = Modifier                        .fillMaxSize()                        .background(colorResource(id = R.color.darkgreen))                ) {                    Scaffold(                        modifier = Modifier.fillMaxSize(),                        containerColor = Color.Transparent                    ) { innerPadding ->                        Box(                            modifier = Modifier                                .fillMaxSize()                                .padding(innerPadding),                            contentAlignment = Alignment.Center                        ) {                            PixelDog()                        }                    }                }            }        }    }}/** * 橙色像素小狗 + 点击缩放跳跃旋转 + 播放狗叫wav音频 */@Composablefun PixelDog(modifier: Modifier = Modifier) {    val context = LocalContext.current    var jumpTrigger by remember { mutableStateOf(false) }    val mediaPlayer = remember {        MediaPlayer.create(context, R.raw.dog_bark)    }    DisposableEffect(Unit) {        onDispose {            mediaPlayer.release()        }    }    val jumpOffset: Dp by animateDpAsState(        targetValue = if (jumpTrigger) (-200).dp else 0.dp,        animationSpec = tween(durationMillis = 400),        finishedListener = { jumpTrigger = false }    )    val rotateAngle: Float by animateFloatAsState(        targetValue = if (jumpTrigger) -360f else 0f,        animationSpec = tween(durationMillis = 400)    )    funonDogClick() {        jumpTrigger = true        mediaPlayer.seekTo(0)        mediaPlayer.start()    }    Box(        modifier = modifier            .size(120.dp)            .clickable { onDogClick() }            .graphicsLayer {                translationY = jumpOffset.toPx()                rotationZ = rotateAngle            },        contentAlignment = Alignment.Center    ) {        Box(            modifier = Modifier                .size(300.dp)                .background(Color(0xFFfe8862))        )    }}@Preview@Composablefun Preview() {    PetTheme {        Box(            modifier = Modifier                .fillMaxSize()                .background(colorResource(id = R.color.darkgreen))        ) {            Scaffold(                modifier = Modifier.fillMaxSize(),                containerColor = Color.Transparent            ) { innerPadding ->                Box(                    modifier = Modifier                        .fillMaxSize()                        .padding(innerPadding),                    contentAlignment = Alignment.Center                ) {                    PixelDog()                }            }        }    }}
这一套组合技非常爽,不过agent的API有报错,不是我的问题。

400 是服务端参数校验失败,代表客户端(Android Studio 里的 AI Agent 插件)发给 DeepSeek 的请求格式不符合接口最新要求;

关键词 reasoning_content:DeepSeek 近期更新了思考链(深度思考)模式的入参强制校验,旧版插件没有携带这个字段,直接被 API 拒绝返回 400。

06四个小时内点击超过10次会有宠物变形动画并打饱嗝
(1)同样,在耳聆网下载音频

小狗叫 许可:CC-BY-NC 作者:centianhua 来源:耳聆网 https://www.ear0.com/sound/38121

(2)把mp3命名为burp.mp3复制粘贴给res/raw文件夹

(3)修改代码:

package com.example.petimport android.media.MediaPlayerimport android.os.Bundleimport androidx.activity.ComponentActivityimport androidx.activity.compose.setContentimport androidx.activity.enableEdgeToEdgeimport androidx.compose.animation.core.animateDpAsStateimport androidx.compose.animation.core.animateFloatAsStateimport androidx.compose.animation.core.tweenimport androidx.compose.foundation.backgroundimport androidx.compose.foundation.clickableimport androidx.compose.foundation.layout.Boximport androidx.compose.foundation.layout.fillMaxSizeimport androidx.compose.foundation.layout.paddingimport androidx.compose.foundation.layout.sizeimport androidx.compose.runtime.Composableimport androidx.compose.runtime.DisposableEffectimport androidx.compose.runtime.getValueimport androidx.compose.runtime.mutableLongStateOfimport androidx.compose.runtime.mutableIntStateOfimport androidx.compose.runtime.mutableStateOfimport androidx.compose.runtime.rememberimport androidx.compose.runtime.saveable.rememberSaveableimport androidx.compose.runtime.setValueimport androidx.compose.ui.Alignmentimport androidx.compose.ui.Modifierimport androidx.compose.ui.graphics.Colorimport androidx.compose.ui.graphics.graphicsLayerimport androidx.compose.ui.platform.LocalContextimport androidx.compose.ui.res.colorResourceimport androidx.compose.ui.tooling.preview.Previewimport androidx.compose.ui.unit.Dpimport androidx.compose.ui.unit.dpimport com.example.pet.ui.theme.PetThemeclass MainActivity : ComponentActivity() {    override funonCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        enableEdgeToEdge()        setContent {            PetTheme {                Box(                    modifier = Modifier                        .fillMaxSize()                        .background(colorResource(id = R.color.darkgreen))                ) {                    androidx.compose.material3.Scaffold(                        modifier = Modifier.fillMaxSize(),                        containerColor = Color.Transparent                    ) { innerPadding ->                        Box(                            modifier = Modifier                                .fillMaxSize()                                .padding(innerPadding),                            contentAlignment = Alignment.Center                        ) {                            PixelDog()                        }                    }                }            }        }    }}@Composablefun PixelDog(modifier: Modifier = Modifier) {    val context = LocalContext.current    val FOUR_HOUR_MILLIS = 4 * 60 * 60 * 1000    var firstClickTime by rememberSaveable { mutableLongStateOf(0L) }    var clickCount by rememberSaveable { mutableIntStateOf(0) }    var triggerNormalAnim by remember { mutableStateOf(false) }    var triggerBurpAnim by remember { mutableStateOf(false) }    val barkPlayer = remember { MediaPlayer.create(context, R.raw.dog_bark) }    val burpPlayer = remember { MediaPlayer.create(context, R.raw.burp) }    DisposableEffect(barkPlayer, burpPlayer) {        onDispose {            barkPlayer.release()            burpPlayer.release()        }    }    funisBurpMode()Boolean {        if (firstClickTime == 0Lreturn false        val now = System.currentTimeMillis()        val timeRange = now - firstClickTime        return timeRange <= FOUR_HOUR_MILLIS && clickCount > 10    }    val jumpOffset: Dp by animateDpAsState(        targetValue = if (triggerNormalAnim) (-200).dp else 0.dp,        animationSpec = tween(400),        finishedListener = { triggerNormalAnim = false }    )    val rotateAngle: Float by animateFloatAsState(        targetValue = if (triggerNormalAnim) -360f else 0f,        animationSpec = tween(400)    )    val scaleX by animateFloatAsState(        targetValue = if (triggerBurpAnim) 1.3f else 1f,        animationSpec = tween(450),        finishedListener = { triggerBurpAnim = false }    )    val scaleY by animateFloatAsState(        targetValue = if (triggerBurpAnim) 0.6f else 1f,        animationSpec = tween(450)    )    funhandleClick() {        val currentTime = System.currentTimeMillis()        if (firstClickTime != 0L && currentTime - firstClickTime > FOUR_HOUR_MILLIS) {            clickCount = 0            firstClickTime = 0        }        if (firstClickTime == 0L) {            firstClickTime = currentTime        }        clickCount += 1        if (isBurpMode()) {            triggerBurpAnim = true            burpPlayer.seekTo(0)            burpPlayer.start()        } else {            triggerNormalAnim = true            barkPlayer.seekTo(0)            barkPlayer.start()        }    }    Box(        modifier = modifier            .size(120.dp)            .clickable { handleClick() }            .graphicsLayer {                if (isBurpMode()) {                    this.scaleX = scaleX                    this.scaleY = scaleY                } else {                    translationY = jumpOffset.toPx()                    rotationZ = rotateAngle                }            },        contentAlignment = Alignment.Center    ) {        Box(            modifier = Modifier                .size(300.dp)                .background(Color(0xFFfe8862))        )    }}@Preview@Composablefun Preview() {    PetTheme {        Box(            modifier = Modifier                .fillMaxSize()                .background(colorResource(id = R.color.darkgreen))        ) {            androidx.compose.material3.Scaffold(                modifier = Modifier.fillMaxSize(),                containerColor = Color.Transparent            ) { innerPadding ->                Box(                    modifier = Modifier                        .fillMaxSize()                        .padding(innerPadding),                    contentAlignment = Alignment.Center                ) {                    PixelDog()                }            }        }    }}

07每天早上八点、中午十二点、晚上十点和用户打招呼,调用手机通知权限,发一条消息,分别从话术库中选择一条发送,提示音是狗叫

(1)修改 AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?><manifestxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"package="com.example.pet">    <!-- 权限全部写在application外面,manifest内部 -->    <uses-permissionandroid:name="android.permission.POST_NOTIFICATIONS"/>    <uses-permissionandroid:name="android.permission.SCHEDULE_EXACT_ALARM"/>    <uses-permissionandroid:name="android.permission.USE_EXACT_ALARM"/>    <applicationandroid:allowBackup="true"android:dataExtractionRules="@xml/data_extraction_rules"android:fullBackupContent="@xml/backup_rules"android:icon="@drawable/ic_launcher_background"android:label="@string/app_name"android:roundIcon="@drawable/ic_launcher_background"android:supportsRtl="true"android:theme="@style/Theme.Pet">        <!-- 广播接收器必须放在application标签内部 -->        <receiverandroid:name=".NotificationReceiver"android:exported="false"/>        <activityandroid:name=".MainActivity"android:exported="true"android:label="@string/app_name"android:theme="@style/Theme.Pet">            <intent-filter>                <actionandroid:name="android.intent.action.MAIN" />                <categoryandroid:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>    </application></manifest>

(2)新建NotificationReceiver.kt

新建于这个文件夹中,类型选择class

package com.example.petimport android.content.BroadcastReceiverimport android.content.Contextimport android.content.Intentimport android.content.pm.PackageManagerimport android.media.MediaPlayerimport androidx.core.app.NotificationCompatimport androidx.core.app.NotificationManagerCompatimport androidx.core.content.ContextCompatimport kotlin.random.Randomclass NotificationReceiver : BroadcastReceiver() {    private val greetList = listOf(        "早上好,新的一天元气满满!",        "起床啦,今天也要开开心心",        "午饭时间到,记得好好吃饭哦",        "中午歇一会,放松一下吧",        "晚上好,忙碌一天辛苦啦",        "夜深了,早点休息不要熬夜"//这些台词我后面都改成不分时间段的了    )    override funonReceive(context: Context?, intent: Intent?) {        if (context == nullreturn        val selectText = greetList[Random.nextInt(greetList.size)]        val player = MediaPlayer.create(context, R.raw.dog_bark)        player.start()        player.setOnCompletionListener {            it.release()        }        // 判断通知权限        if (ContextCompat.checkSelfPermission(                context,                android.Manifest.permission.POST_NOTIFICATIONS            ) == PackageManager.PERMISSION_GRANTED        ) {            try {                val notification = NotificationCompat.Builder(context, "pet_remind")                    .setSmallIcon(R.drawable.ic_launcher_background)                    .setContentTitle("你的小宠物")                    .setContentText(selectText)                    .setPriority(NotificationCompat.PRIORITY_HIGH)                    .build()                NotificationManagerCompat.from(context).notify(1001, notification)            } catch (e: SecurityException) {                // 用户拒绝权限时什么都不执行            }        }    }}

(3)新建ScheduleManager.kt,类型选择object

package com.example.petimport android.app.AlarmManagerimport android.app.PendingIntentimport android.content.Contextimport android.content.Intentimport java.util.*object ScheduleManager {    funsetupAllAlarm(context: Context) {        setAlarm(context, 801001)        setAlarm(context, 1201002)        setAlarm(context, 2201003)    }    private funsetAlarm(context: Context, hour: Int, minute: Int, requestCode: Int) {        val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager        val intent = Intent(context, NotificationReceiver::class.java)        val pendingIntent = PendingIntent.getBroadcast(            context, requestCode, intent,            PendingIntent.FLAG_IMMUTABLE        )        val calendar = Calendar.getInstance().apply {            timeInMillis = System.currentTimeMillis()            set(Calendar.HOUR_OF_DAY, hour)            set(Calendar.MINUTE, minute)            set(Calendar.SECOND, 0)        }        if (calendar.timeInMillis <= System.currentTimeMillis()) {            calendar.add(Calendar.DAY_OF_YEAR, 1)        }        alarmManager.setExactAndAllowWhileIdle(            AlarmManager.RTC_WAKEUP,            calendar.timeInMillis,            pendingIntent        )    }    funcancelAllAlarm(context: Context) {        val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager        listOf(100110021003).forEach { code ->            val intent = Intent(context, NotificationReceiver::class.java)            val pendingIntent = PendingIntent.getBroadcast(                context, code, intent, PendingIntent.FLAG_IMMUTABLE            )            alarmManager.cancel(pendingIntent)        }    }}

(4)在build.gradle.kts中添加依赖

dependencies {    implementation("androidx.work:work-runtime-ktx:2.10.0")}

(5)修改MainActivity.kt

package com.example.petimport android.media.MediaPlayerimport android.os.Bundleimport androidx.activity.ComponentActivityimport androidx.activity.compose.setContentimport androidx.activity.enableEdgeToEdgeimport androidx.compose.animation.core.animateDpAsStateimport androidx.compose.animation.core.animateFloatAsStateimport androidx.compose.animation.core.tweenimport androidx.compose.foundation.backgroundimport androidx.compose.foundation.clickableimport androidx.compose.foundation.layout.Boximport androidx.compose.foundation.layout.fillMaxSizeimport androidx.compose.foundation.layout.paddingimport androidx.compose.foundation.layout.sizeimport androidx.compose.runtime.Composableimport androidx.compose.runtime.DisposableEffectimport androidx.compose.runtime.getValueimport androidx.compose.runtime.mutableLongStateOfimport androidx.compose.runtime.mutableIntStateOfimport androidx.compose.runtime.mutableStateOfimport androidx.compose.runtime.rememberimport androidx.compose.runtime.saveable.rememberSaveableimport androidx.compose.runtime.setValueimport androidx.compose.ui.Alignmentimport androidx.compose.ui.Modifierimport androidx.compose.ui.graphics.Colorimport androidx.compose.ui.graphics.graphicsLayerimport androidx.compose.ui.platform.LocalContextimport androidx.compose.ui.res.colorResourceimport androidx.compose.ui.tooling.preview.Previewimport androidx.compose.ui.unit.Dpimport androidx.compose.ui.unit.dpimport com.example.pet.ui.theme.PetThemeclass MainActivity : ComponentActivity() {    // 把权限申请的 launcher 放到方法外面,作为成员变量    private val requestPermissionLauncher =        registerForActivityResult(androidx.activity.result.contract.ActivityResultContracts.RequestPermission()) { granted ->            if (granted) {                ScheduleManager.setupAllAlarm(this)            }        }    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        enableEdgeToEdge()        setContent {            //你的Compose页面代码不变            PetTheme {                Box(                    modifier = Modifier                        .fillMaxSize()                        .background(colorResource(id = R.color.darkgreen))                ) {                    androidx.compose.material3.Scaffold(                        modifier = Modifier.fillMaxSize(),                        containerColor = Color.Transparent                    ) { innerPadding ->                        Box(                            modifier = Modifier                                .fillMaxSize()                                .padding(innerPadding),                            contentAlignment = Alignment.Center                        ) {                            PixelDog()                        }                    }                }            }        }        requestNotificationPermission()    }    private fun requestNotificationPermission() {        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) {            requestPermissionLauncher.launch(android.Manifest.permission.POST_NOTIFICATIONS)        } else {            ScheduleManager.setupAllAlarm(this)        }    }}@Composablefun PixelDog(modifier: Modifier = Modifier) {    val context = LocalContext.current    val FOUR_HOUR_MILLIS = 4 * 60 * 60 * 1000    var firstClickTime by rememberSaveable { mutableLongStateOf(0L) }    var clickCount by rememberSaveable { mutableIntStateOf(0) }    var triggerNormalAnim by remember { mutableStateOf(false) }    var triggerBurpAnim by remember { mutableStateOf(false) }    val barkPlayer = remember { MediaPlayer.create(context, R.raw.dog_bark) }    val burpPlayer = remember { MediaPlayer.create(context, R.raw.burp) }    DisposableEffect(barkPlayer, burpPlayer) {        onDispose {            barkPlayer.release()            burpPlayer.release()        }    }    fun isBurpMode(): Boolean {        if (firstClickTime == 0L) return false        val now = System.currentTimeMillis()        val timeRange = now - firstClickTime        return timeRange <= FOUR_HOUR_MILLIS && clickCount > 10    }    val jumpOffset: Dp by animateDpAsState(        targetValue = if (triggerNormalAnim) (-200).dp else 0.dp,        animationSpec = tween(400),        finishedListener = { triggerNormalAnim = false }    )    val rotateAngle: Float by animateFloatAsState(        targetValue = if (triggerNormalAnim) -360f else 0f,        animationSpec = tween(400)    )    val scaleX by animateFloatAsState(        targetValue = if (triggerBurpAnim) 1.3f else 1f,        animationSpec = tween(450),        finishedListener = { triggerBurpAnim = false }    )    val scaleY by animateFloatAsState(        targetValue = if (triggerBurpAnim) 0.6f else 1f,        animationSpec = tween(450)    )    fun handleClick() {        val currentTime = System.currentTimeMillis()        if (firstClickTime != 0L && currentTime - firstClickTime > FOUR_HOUR_MILLIS) {            clickCount = 0            firstClickTime = 0        }        if (firstClickTime == 0L) {            firstClickTime = currentTime        }        clickCount += 1        if (isBurpMode()) {            triggerBurpAnim = true            burpPlayer.seekTo(0)            burpPlayer.start()        } else {            triggerNormalAnim = true            barkPlayer.seekTo(0)            barkPlayer.start()        }    }    Box(        modifier = modifier            .size(120.dp)            .clickable { handleClick() }            .graphicsLayer {                if (isBurpMode()) {                    this.scaleX = scaleX                    this.scaleY = scaleY                } else {                    translationY = jumpOffset.toPx()                    rotationZ = rotateAngle                }            },        contentAlignment = Alignment.Center    ) {        Box(            modifier = Modifier                .size(300.dp)                .background(Color(0xFFfe8862))        )    }}@Preview@Composablefun Preview() {    PetTheme {        Box(            modifier = Modifier                .fillMaxSize()                .background(colorResource(id = R.color.darkgreen))        ) {            androidx.compose.material3.Scaffold(                modifier = Modifier.fillMaxSize(),                containerColor = Color.Transparent            ) { innerPadding ->                Box(                    modifier = Modifier                        .fillMaxSize()                        .padding(innerPadding),                    contentAlignment = Alignment.Center                ) {                    PixelDog()                }            }        }    }}

08在小米13上部署测试

(1)开启手机开发者模式,设置/我的设备/全部参数与信息,点击OS版本七次,进入开发者模式

(2)设置/更多设置/开发者选项,开启USB调试和USB安装权限

(3)数据线连接电脑和手机

(4)Android Studio识别手机,点运行

于是手机上就会多出pet应用

并且能够运行,期待到点给我发消息。

测试结果:启动时有申请通知权限的提示框,但是到点并没有弹出通知,测试安卓studio的虚拟机也是同样结果。

更改NotificationReceiver的代码:

package com.example.petimport android.content.BroadcastReceiverimport android.content.Contextimport android.content.Intentimport android.content.pm.PackageManagerimport android.media.MediaPlayerimport android.os.Buildimport androidx.core.app.NotificationCompatimport androidx.core.app.NotificationManagerCompatimport androidx.core.content.ContextCompatimport android.app.NotificationChannelimport android.app.NotificationManagerimport kotlin.random.Randomclass NotificationReceiver : BroadcastReceiver() {    private val greetList = listOf(        "早上好,新的一天元气满满!",        "起床啦,今天也要开开心心",        "午饭时间到,记得好好吃饭哦",        "中午歇一会,放松一下吧",        "晚上好,忙碌一天辛苦啦",        "夜深了,早点休息不要熬夜"    )    private val CHANNEL_ID = "pet_remind"    override funonReceive(context: Context?, intent: Intent?) {        if (context == nullreturn        // Android8.0+ 必须创建通知通道,否则通知不会弹出        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {            val channel = NotificationChannel(                CHANNEL_ID,                "宠物定时问候",                NotificationManager.IMPORTANCE_HIGH            ).apply {                setShowBadge(true)            }            val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager            notificationManager.createNotificationChannel(channel)        }        val selectText = greetList[Random.nextInt(greetList.size)]        val player = MediaPlayer.create(context, R.raw.dog_bark)        player.start()        player.setOnCompletionListener { it.release() }        if (ContextCompat.checkSelfPermission(                context,                android.Manifest.permission.POST_NOTIFICATIONS            ) == PackageManager.PERMISSION_GRANTED        ) {            try {                val notification = NotificationCompat.Builder(context, CHANNEL_ID)                    .setSmallIcon(R.drawable.ic_launcher_background)                    .setContentTitle("你的小宠物")                    .setContentText(selectText)                    .setPriority(NotificationCompat.PRIORITY_HIGH)                    .build()                NotificationManagerCompat.from(context).notify(1001, notification)            } catch (_: SecurityException) {}        }    }}

虚拟机通知成功。

重新安装pet。

但是第二次试发现只有在界面的时候才会发通知,后台无法运行。

于是在小米应用设置中修改pet应用权限:改了电池消耗和自启动。

通知功能就正常了。

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-24 03:42:50 HTTP/1.1 GET : https://www.yeyulingfeng.com/a/857161.html
  2. 运行时间 : 0.157139s [ 吞吐率:6.36req/s ] 内存消耗:4,812.99kb 文件加载:145
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=64bbcec549533f4b2179b3723b118041
  1. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_static.php ( 6.05 KB )
  7. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/ralouphie/getallheaders/src/getallheaders.php ( 1.60 KB )
  10. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  11. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  12. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  13. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  14. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  15. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  16. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  17. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  18. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  19. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions_include.php ( 0.16 KB )
  21. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions.php ( 5.54 KB )
  22. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  23. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  24. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  25. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/provider.php ( 0.19 KB )
  26. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  27. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  28. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  29. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/common.php ( 0.03 KB )
  30. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  32. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/alipay.php ( 3.59 KB )
  33. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  34. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/app.php ( 0.95 KB )
  35. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cache.php ( 0.78 KB )
  36. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/console.php ( 0.23 KB )
  37. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cookie.php ( 0.56 KB )
  38. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/database.php ( 2.48 KB )
  39. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/filesystem.php ( 0.61 KB )
  40. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/lang.php ( 0.91 KB )
  41. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/log.php ( 1.35 KB )
  42. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/middleware.php ( 0.19 KB )
  43. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/route.php ( 1.89 KB )
  44. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/session.php ( 0.57 KB )
  45. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/trace.php ( 0.34 KB )
  46. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/view.php ( 0.82 KB )
  47. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/event.php ( 0.25 KB )
  48. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  49. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/service.php ( 0.13 KB )
  50. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/AppService.php ( 0.26 KB )
  51. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  52. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  53. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  54. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  55. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  56. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/services.php ( 0.14 KB )
  57. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  58. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  59. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  60. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  61. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  62. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  63. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  64. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  65. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  66. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  67. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  68. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  69. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  70. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  71. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  72. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  73. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  74. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  75. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  76. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  77. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  78. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  79. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  80. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  81. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  82. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  83. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  84. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  85. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  86. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  87. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/Request.php ( 0.09 KB )
  88. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  89. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/middleware.php ( 0.25 KB )
  90. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  91. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  92. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  93. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  94. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  95. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  96. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  97. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  98. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  99. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  100. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  101. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  102. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  103. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/route/app.php ( 3.94 KB )
  104. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  105. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  106. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Index.php ( 9.87 KB )
  108. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/BaseController.php ( 2.05 KB )
  109. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  110. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  111. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  112. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  113. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  114. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  115. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  116. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  117. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  118. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  119. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  120. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  121. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  122. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  123. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  124. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  125. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  126. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  127. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  128. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  129. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  130. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  131. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  132. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  133. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  134. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  135. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Es.php ( 3.30 KB )
  136. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  137. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  138. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  139. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  140. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  141. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  142. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  143. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  144. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/runtime/temp/c935550e3e8a3a4c27dd94e439343fdf.php ( 31.50 KB )
  145. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000432s ] mysql:host=127.0.0.1;port=3306;dbname=wenku;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000622s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000287s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.007707s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000600s ]
  6. SELECT * FROM `set` [ RunTime:0.025563s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000842s ]
  8. SELECT * FROM `article` WHERE `id` = 857161 LIMIT 1 [ RunTime:0.000493s ]
  9. UPDATE `article` SET `lasttime` = 1784835771 WHERE `id` = 857161 [ RunTime:0.021096s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 64 LIMIT 1 [ RunTime:0.001664s ]
  11. SELECT * FROM `article` WHERE `id` < 857161 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000572s ]
  12. SELECT * FROM `article` WHERE `id` > 857161 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000412s ]
  13. SELECT * FROM `article` WHERE `id` < 857161 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.002437s ]
  14. SELECT * FROM `article` WHERE `id` < 857161 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.007783s ]
  15. SELECT * FROM `article` WHERE `id` < 857161 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.001538s ]
0.158887s