<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Wesley&#39;s Blog</title>
  <icon>https://iwesley.top/icon.png</icon>
  <subtitle>我未曾珍惜的，我不再拥有。</subtitle>
  <link href="https://iwesley.top/atom.xml" rel="self"/>
  
  <link href="https://iwesley.top/"/>
  <updated>2026-08-08T13:11:39.100Z</updated>
  <id>https://iwesley.top/</id>
  
  <author>
    <name>Wesley</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>青春的涟漪</title>
    <link href="https://iwesley.top/article/f5f43a7c/"/>
    <id>https://iwesley.top/article/f5f43a7c/</id>
    <published>2026-08-08T13:05:12.000Z</published>
    <updated>2026-08-08T13:11:39.100Z</updated>
    
    <content type="html"><![CDATA[<p>首发于：<a href="https://mp.weixin.qq.com/s/GgY_PweX3Dzjypt33DC8eg">https://mp.weixin.qq.com/s/GgY_PweX3Dzjypt33DC8eg</a></p><p>第一次听说“青春的涟漪”这个概念，是在罗永浩的十字路口里大鹏谈到的，我觉得很适合作为今天这篇文章的题目。</p><h3 id="一个拧巴的人"><a href="#一个拧巴的人" class="headerlink" title="一个拧巴的人"></a>一个拧巴的人</h3><p>我认识一个人。</p><p>他敏感、内向，重情谊，却缺乏勇气，常常把原本简单的事情想得过于复杂，将自己困在拧巴与内耗之中。</p><p>他错把自己的顾虑看作体贴，把迂回视为分寸。他明明给出了答案，却总担心答案不够好；明明守住了边界，又害怕自己的疏远显得冷漠无情。于是，简单的话到了他那里可能要铺垫一圈，原本普通的过往也会在心里被反复审判多年。他的善意是真的，他的胆怯也是真的，而他的拧巴，可能是始终不能坦然承认：一个人即使没有做错什么，也仍可能让别人失望。</p><h3 id="他与她们"><a href="#他与她们" class="headerlink" title="他与她们"></a>他与她们</h3><p>初三那年，A 同学主动加了他的 QQ。他们之前其实并不认识，也不在同一个班级，不知道她是怎么找到他联系方式的。</p><p>他们在学校见面的机会很少，更多的只是偶尔在路上碰到。关于她的大部分记忆，基本都来源于线上聊天、QQ 空间和朋友圈。</p><p>高二那年，电视《何以笙箫默》热播，他们都在追看，也分享过观后感受。他曾借给她一本刘同的《谁的青春不迷茫》，上面写着密密麻麻带有鸡汤的笔记，她觉得他是一个很励志的人。她送了他一本七堇年的《被窝是青春的坟墓》，但他没仔细看过，因为他当时开始对这类青春文学不感兴趣了。</p><p>好像还是同一年，她通过 QQ 匿名聊天窗口询问他一些感情上的事情。他起初误以为对面的人是 B 同学，有点不知所措。因为那段时间，B 同学在 QQ 空间里向他写了一些表达好感的话。</p><p>他没有接受，说现在并不是谈感情的时候，高中阶段还是应该以读书为重。</p><p>后来，对方主动说明身份是A 同学，说跟他开了一个玩笑而已，不要当真。他有些意外，只是小说里写的那种突然冒出来的悸动，并没有发生在他身上。</p><p>高考后的一个秋天，A 过生日，他写了一段祝福。开头是一连串蛋糕、西瓜、面条等表情，接着祝她每天保持好心情。</p><p>然后，他开始谈大学。</p><p>他说大学更加自由，也更需要自制力，要找到真正喜欢的方向，也要坚持做自己认为正确的事。他还引用罗永浩，韩寒和余华等句子，最后写下：</p><p>永远年轻，永远热泪盈眶。</p><p>一个朋友过生日，他却像临时召开了一场青年成长座谈会。</p><p>他忘了是高考结束后还是大学第一个寒假，他们似乎有过唯一一次真正坐下来聊天的机会，就在她家附近的糖水店。聊的内容早已忘光，他只记得骑车走的时候，她拍了一张他骑车背影的照片发给他。自那以后，他们再也没有见过，但也没有完全走散。偶尔在微信上聊聊近况，谈起共同喜欢的歌曲，也总能聊得轻松而愉快。</p><p>B 同学和A 同学不同。她与他是同班同学，面对的是同一块黑板，经历过相同的班级活动，也曾在课室走廊里停下来聊天。她思维清晰，说话不转弯抹角，也指出过他的缺点。相比之下，他说话要多一点拘谨。</p><p>有一段时间，B 同学会在 QQ 空间写下一些 cue 他的话。</p><p>他看到了，却没有主动挑明。不是因为担心自作多情，而是他本能地想躲开这件事。他不愿面对一份自己无法回应的感情，也害怕话一旦说破，两个人连原本自然的相处都无法维持。于是，他假装没有看到，也没有向前靠近。</p><p>高考刚结束不久，他又一次躲进了文字里。他在手机便签写下一封没有信纸的长信，随后发给她。仿佛只要隔着屏幕，他就能从容谈论高三、大学、理想和未来，而不必当面直视对方的眼神，也不必应付那些可能的追问。他把难以面对的关系整理成一段段工整的文字，把本该发生在两个人之间的对话，变成一场由他独自控制节奏的陈述。写信当然需要勇气，但对他而言，文字同时也是一处藏身之所。</p><p>他先写做题、考试和未来的压力，又写大学、社会、理想与价值观，希望她保护好自己，找到真正喜欢的方向。</p><p>直到最后，他才写到两人之间那些没有说破的事。他说，她过去表现出来的一些东西，他其实知道，只是不知道该如何处理。</p><p>最后，他写下一句：</p><p>I’m sorry.</p><p>那不是情书，也没有告白或挽留。它更像一封解释：我无法以你期待的方式回应，却仍然在意你作为朋友是否过得好。他没有能力把这些意思压缩成几句简单的话，于是绕过高三、大学、社会与人生，才笨拙地抵达一句”I’m sorry.”</p><p>大一后的寒假，他们还曾在家乡新开的麦当劳见过一次，但已经记不清聊过什么了。那次以后，再也没有见过。</p><h3 id="青春的涟漪"><a href="#青春的涟漪" class="headerlink" title="青春的涟漪"></a>青春的涟漪</h3><p>他偶尔还是会想起她们，也不是想重新开启早已经结束的故事。即使回到过去，可能一切也不会改变。至于那一刻想起的究竟是她们、那段青春，还是当时那个傻x的自己，他始终没有分清。</p><p>一个人在十八岁时，很难准确区分爱情、友情、善意与责任。他只是本能地拒绝了自己无法回应的感情，同时又舍不得把一个原本珍惜的朋友，从生命里简单地划掉，他做得并不完美。</p><p>她们曾向他表达过心意，他没有接受，却也从未因此否定她们。对他而言，她们依然是青春里值得珍惜的朋友。这些年，彼此的联系虽然少了很多，却没有真正断开。他也知道她们已一步步走向更好的未来，在各自擅长的领域里找到位置，成为了自己人生的主角。</p><p>而他始终愿她们平安喜乐。</p><p>水面早已恢复平静。只是在偶尔回望时，记忆深处仍会泛起一圈淡淡的波纹。</p><p>那是青春的涟漪。</p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;首发于：&lt;a</summary>
        
      
    
    
    
    <category term="随笔" scheme="https://iwesley.top/categories/%E9%9A%8F%E7%AC%94/"/>
    
    
    <category term="随笔" scheme="https://iwesley.top/tags/%E9%9A%8F%E7%AC%94/"/>
    
  </entry>
  
  <entry>
    <title>基于 KMP 实现一个跨平台音乐播放器</title>
    <link href="https://iwesley.top/article/b62bc8f/"/>
    <id>https://iwesley.top/article/b62bc8f/</id>
    <published>2026-04-11T14:02:25.000Z</published>
    <updated>2026-05-08T16:13:35.000Z</updated>
    
    <content type="html"><![CDATA[<img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260508220635732.png" alt="ig_090a64adea1992790169fde46338f8819186c55dabc269e1da" style="zoom:50%;" /><p><a href="https://mp.weixin.qq.com/s/qWoGIy7gtmNdAmJiV4S0Ig">开源一个跨平台音乐播放器 LynMusic</a></p><p><a href="https://mp.weixin.qq.com/s/DGohuAOSEOk09MK-bhzdjA">LynMusic 能力再进化：适配电视、车机与投屏</a></p><p>计算机先驱艾伦·凯说过“真正认真对待软件的人应该制造自己的硬件（People who are really serious about software should make their own hardware）。” 乔布斯也曾经在发布会引用过这句话。硬件其实还是很难自己一个人设计并制造的，但在 AI 时代，自己设计并开发完成一款软件，难度已经大大下降了。作为一个安卓开发者，我全程使用 codex 完成了这个多端播放器的开发。</p><h2 id="为什么做这个播放器"><a href="#为什么做这个播放器" class="headerlink" title="为什么做这个播放器"></a>为什么做这个播放器</h2><p>第一，虽然市面上已经有很多音乐播放器了，但搜索歌词太难用了，有些歌还不一定能搜到；第二，想学习一下 KMP；第三，因为有了 codex 这样的编程工具，实现难度大大下降；第四，可以自主决策功能和界面。</p><h2 id="LynMusic-聆听音乐"><a href="#LynMusic-聆听音乐" class="headerlink" title="LynMusic 聆听音乐"></a>LynMusic 聆听音乐</h2><p>跨平台，支持安卓(含车机、电视)、iOS、macOS，Windows，Linux。（ps：由于苹果需要付费的开发者账号，目前ios不支持在 App Store 下载，只能自己编译使用）。</p><p>采用 kotlin compose 进行开发，不同于一些音乐软件采用web跨平台方案，kmp 在安卓和 ios 能获得更加好的原生性能体验。</p><p>支持导入本地文件夹、Samba、WebDAV、Navidrome 里面的音乐。一些支持 WebDav 的云盘也可以，比如 pCloud、坚果云、阿里云等。强大的歌词搜索功能，支持自己引入几乎市面上存在的 api 源。</p><p>歌词分享功能，可以自定义分享字体。</p><p>支持定时播放、投屏等。TV 端还可以作为 render，接收音乐和视频投屏。</p><p>支持离线下载。如果在外面不能内网穿透到家中的服务器，还可以把 navidrome 等音乐下载到本地，聆听音乐时支持选择已经下载的音乐。</p><p>音乐标签。可以自己编辑音乐的元数据和封面等。</p><p>自定义功能多，比如是否启动自动播放、navidrome 多档音质选择、显示大小、自定义主题等。还可以在喜欢列表，按歌手、专辑来筛选播放。</p><h2 id="产品图"><a href="#产品图" class="headerlink" title="产品图"></a>产品图</h2><h3 id="手机"><a href="#手机" class="headerlink" title="手机"></a>手机</h3><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260508234744153.jpg" alt="phone_main_ui" style="zoom: 25%;" /><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260508235537305.png" alt="Screenshot_20260508_233705" style="zoom:25%;" /><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260508235641439.png" alt="Screenshot_20260508_233811" style="zoom:25%;" /><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260508235706269.png" alt="Screenshot_20260508_233842" style="zoom:25%;" /><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260508235729372.png" alt="Screenshot_20260508_233854" style="zoom:25%;" /><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260508235745349.png" alt="Screenshot_20260508_233923" style="zoom:25%;" /><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260508235802127.png" alt="Screenshot_20260508_233941" style="zoom:25%;" /><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260508235827984.png" alt="Screenshot_20260508_233959" style="zoom:25%;" /><h2 id="平板或者桌面端"><a href="#平板或者桌面端" class="headerlink" title="平板或者桌面端"></a>平板或者桌面端</h2><p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260508235914807.png" alt="Snipaste_2026-05-08_23-41-55"></p><p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260508235934936.png" alt="Snipaste_2026-05-08_23-42-46"></p><p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260508235955453.png" alt="Snipaste_2026-05-08_23-43-07"></p><p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260509000018804.png" alt="Snipaste_2026-05-08_23-43-18"></p><p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260509000907727.png" alt="Snipaste_2026-05-09_00-08-31"></p><p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260509000135712.png" alt="image-20260509000135644"></p><p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260509000254821.png" alt="image-20260509000254752"></p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260509000311531.png" alt="唯一-11lyrics-share" style="zoom:25%;" /><h3 id="车机"><a href="#车机" class="headerlink" title="车机"></a>车机</h3><p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260509000350791.png" alt="mmexport1777828602457"></p><p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260509000418032.png" alt="mmexport1777828674900"></p><h3 id="TV"><a href="#TV" class="headerlink" title="TV"></a>TV</h3><p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260509000449621.png" alt="Screenshot_20260508_234418"></p><p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260509000510389.png" alt="Screenshot_20260508_234440"></p><p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260509000534696.png" alt="Screenshot_20260508_234507"></p><p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260509000550795.png" alt="Screenshot_20260508_234527"></p><p>作为投屏渲染端，可以自动匹配歌词：<br><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260509000605427.png" alt="Screenshot_20260508_234611"></p><h2 id="开源地址"><a href="#开源地址" class="headerlink" title="开源地址"></a>开源地址</h2><p><a href="https://github.com/wesley666/LynMusic/">https://github.com/wesley666/LynMusic/</a></p><blockquote><p>桌面版本要先安装 vlc 播放器，LynMusic 使用 vlc 的接口播放音乐。<br>mac 版本需要执行命令才能打开：xattr -dr com.apple.quarantine &#x2F;Applications&#x2F;LynMusic.app。但自己编译的版本不需要。</p></blockquote><p>欢迎使用和提建议。</p><h2 id="Vibe-Coding-的一些心得"><a href="#Vibe-Coding-的一些心得" class="headerlink" title="Vibe Coding 的一些心得"></a>Vibe Coding 的一些心得</h2><p>尽可能采用 sota 模型 和 官方 api，可以节省大量时间，也不用担心中转站的猫腻。</p><p>由于 codex 的 plus 额度缩减，为了满足五一期间的开发 token 需求，我还开通了 100 刀的 pro 会员，目前有 10x 的额度，即使使用 fast 模式也基本用不完。</p><p>尽可能使用 plan 模式来开发和修 bug，除非你能把话说的很清楚，否则需要多轮对话来沟通清楚需求。</p><p>AGENTS.md即使什么都可以没有，也得加上一句：修改代码前要向我二次确认，不要在排查问题阶段擅自改代码。</p><p>AI 的上下文有限，你可能以敏捷开发的方式很快就开发好了一个应用，但如果要变成一个可维护的工程还是需要做好顶层设计的，使用瀑布式开发。</p><p>排查问题要结合日志，不能只靠 AI 逻辑分析。</p><p>AI 有时候是可能降智的，要做好领路人和审计。</p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;img src=&quot;https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260508220635732.png&quot;</summary>
        
      
    
    
    
    <category term="数字生活指南" scheme="https://iwesley.top/categories/%E6%95%B0%E5%AD%97%E7%94%9F%E6%B4%BB%E6%8C%87%E5%8D%97/"/>
    
    
    <category term="随笔" scheme="https://iwesley.top/tags/%E9%9A%8F%E7%AC%94/"/>
    
    <category term="数字生活指南" scheme="https://iwesley.top/tags/%E6%95%B0%E5%AD%97%E7%94%9F%E6%B4%BB%E6%8C%87%E5%8D%97/"/>
    
  </entry>
  
  <entry>
    <title>枪炮、游戏与电视机</title>
    <link href="https://iwesley.top/article/c844aeb9/"/>
    <id>https://iwesley.top/article/c844aeb9/</id>
    <published>2026-03-26T10:26:22.000Z</published>
    <updated>2026-03-27T10:22:32.000Z</updated>
    
    <content type="html"><![CDATA[<p><a href="https://mp.weixin.qq.com/s/tEAxgHgWg8DTuhZngo8Nmg">https://mp.weixin.qq.com/s/tEAxgHgWg8DTuhZngo8Nmg</a></p><blockquote><p>有一本书叫做《枪炮、病菌与钢铁》，2022 年初就被我加入书架了，但一直没读完。想不到今天写文章的时候，无意中又想起来了，那就借此模仿一下题目吧。</p></blockquote><p>2022年9月某一天晚上的时候，一个自从小学毕业后十几年没见过面的邻居 Quan 突然通过QQ联系我，我感觉有点恍如隔世，原来我离开那小时候成长的地方已经有十几年了，直到现在还没有回去过。</p><p>转眼几个月过去，到了春节，我决定回去看看。从环境来看，好像还是十二年前那样，除了一个菜市场变成了大广场，大多数建筑没有变化，公园还是那一个公园，喷池的水依然浑浊，但都有岁月的痕迹，变得更加残旧。我曾在这片小土地生活了六年，有很多玩伴和经历，但岁月不饶人啊，所有的故事都成了回忆。这次我没有碰到熟人，也没有找Quan，而是离那住过的房子一公里开外的马路边驻足遥望片刻，就走了。不是说不想见面，只能说这些年变化太多，物是人非，不再是少年，回忆与现实露出了一条鸿沟，那么期望的东西就可能会变成失落，而我不想互相失望，就把这一切都留在那美好和孤独的回忆里吧。</p><p>2024 年初的时候，我发了一条微博说，两年半和三年半物理上差了一年，但感觉差了一个世纪。这里说的是毕业后多少年了。在那一年，我读完了刘亮程写的《一个人的村庄》，书中对故乡的描写再次让我想起了童年成长的地方，读完后我就写了个评论：</p><blockquote><p>我的故乡虽然都是在同一个县城，但却因为上学的原因分了三个地方，一个是我出生和成长的地方，六七岁后，因为读小学，搬到了离家七八公里的新地方，小学毕业后，就到了县城去了。<br>可能在我心目中，小学那段时期住的地方才是我心目中的“黄沙梁”，那是一段和邻居小伙伴打成一片的日子，那是一段和邻居小伙伴下田进林去公园玩耍的日子，那是一段和小学同学骑车、爬山、烤番薯的日子，还有最逗的数学老师在上课扯淡下课陪我们打羽毛球等等……所有的这一切也随着在一个宁静的中午搬离到县城而永远地留在了记忆中，那时候并没有发现那是一个重要的时刻，也没有和任何小伙伴告别，就这样地，和那些伙伴们分开了。后来在高中期间和小学的一些同学见了面，大多数要好的同学并没有来，而那些邻居小伙伴们，我们再也没有见过。<br>县城读初高中那段时期，虽然也有很多回忆但却不是围绕着邻里展开的，也就不多谈了。现在工作了，租的房子，大家都是关着门的，也没有什么好说的。<br>虽然我心目中的“黄沙梁”再也“回”不去了，但我想把和他们的记忆装进万花筒，这样子我就永远有了新的回忆。</p></blockquote><p>随着年纪增长，怀旧之心再次燃起。所以今年2026年春节的时候，我独自一人再次回到那里，比上次驻留的时间更长，也逛了更多的地方。先回到那生活了6年的出租屋，虽然离得更近，但我还是没有走上去，只是在马路边来来回回，走来走去，然后离开。那个经常去买东西的小卖部没有经营了，但老奶奶还在。上的小学合并到中学校区了，旧址变得破旧不堪，老师和学生都消失了，校园内再也没有升旗仪式，变成了一个废弃场，剩下的是生命力旺盛的榕树，几个拖拉机和几条狗。</p><p>我想以后可能都不会再特意回到那里了，趁着这次机会，把记忆中的童年故事写下来，留个纪念。</p><h2 id="枪炮"><a href="#枪炮" class="headerlink" title="枪炮"></a>枪炮</h2><p>哈哈，当然不是真的武器了，指的是玩具枪和鞭炮。说到玩具枪，一般平时也不会买，只有到春节的时候，有了压岁钱才会买来玩。那时候感觉那种带有望远镜的玩具枪特别帅气，但比较贵，我好像没有买过。只记得我曾经有过一把玩具手枪，上子弹，上膛，扣动扳机，一气呵成，玩的挺开心的。但小时候没有什么安全意识，有一次，我打中了Quan，她当场就哭，然后我当时一冲动就把枪摔到地上砸破，她也恢复平静不哭了。自那以后，我再没有玩过这种枪。更小的时候，还玩过弹弓和竹筒枪，弹弓感觉比玩具枪还危险，还好没有出什么事故。</p><p>除了玩具枪，鞭炮也是春节常见的玩具。我们玩的还挺野的，比如带有绿色引线的鞭炮，我们会等到最后一刻才把它扔出去；把一堆鞭炮里面的炸药倒出来，再压实，然后跑到一个高高的地方，用一个石头砸下去把它引爆。现在回想起来还是感觉挺危险的，那时候 Quan 的姐姐还警告过我们不要这么干，但我们不听。她家的一个亲戚的孩子就没有这么好运气，那个孩子叫东东，长的挺可爱的，但有一个怪癖，耍脾气就喜欢跑到公路上吃土，我们看他这样干时都感觉很可笑。但不幸的是，他再来 Quan 家的时候，发现他被鞭炮意外炸断了手指，要从肚皮上面割肉来补，令我们感觉到很震惊。现在，在深圳看到有人玩鞭炮的时候，我都心有余悸，变得更加胆小，远远就躲开了。</p><h2 id="游戏"><a href="#游戏" class="headerlink" title="游戏"></a>游戏</h2><p>游戏包括现实中的游戏和电子游戏。先说一下现实中的游戏，那时候的我们是没有手机的，放学回家，扔下书包或者写完作业后就跑出去跟邻居玩去了。什么拍纸片、弹玻璃珠、跳飞机、抛石子、丢沙包、捉迷藏等都玩过。记得有一次弹玻璃珠，我运气爆发，赢了一大堆。不过，后来上初中后我就彻底和这些游戏无缘了，那些玻璃珠等玩具也全被我抛弃，也意味着我童年永远地结束了。</p><p>邻居有一个老奶奶，我们经常和她打牌，叫大三大A，有时候也一起玩抛石子，她年纪虽大，但玩起这些来还挺神气的。不过，她已经永远离开我们，但这些时光我不会忘记，下辈子有缘的话可以再一起玩。</p><p>说到电子游戏，好巧不巧，最近我经常在短视频平台看到玩过的那些小霸王游戏，比如魂斗罗、冒险岛、热血物语等等，想起来真的是一个欢乐的游戏时光。那时候，我们先是玩那种黑白小游戏机，带有俄罗斯方块的，但感觉很快就没意思了。换成小霸王游戏机后，才开启了新世界的大门，和同学邻居一起游戏闯关，一起打 boss，那一片片的绿色卡带承载了我们美好的游戏时光。记得有时候玩捉迷藏，玩累了，我就带上一个邻居偷偷溜回去，跟他打游戏，然后别人找进来的时候，还无动于衷说不玩了，挺耍赖的。</p><p>后来，小霸王游戏也不玩，手机游戏开始流行起来了。我有两个游戏记忆深刻，一个是在高新奇手机上面的寿司消消乐和诺基亚 E63 上面的帝国时代，前者到后面计时越来越快，得两个人一起玩才能坚持久一些。后者是我一直以来很喜欢的游戏，从手机到 电脑，直到这些年，偶尔有机会我还是会玩一下。有意思的是，帝国时代的手机版我只有在诺基亚上面玩才有感觉，在那上面配乐才是对的，后面再装在别的手机的 java 模拟器上面，配乐都是错的，所以上了初中后我再也不想玩手机版了。</p><p>游戏一个人玩是孤独的，最好有同伴，我永远怀念和邻居同学们的童年游戏时光。</p><h2 id="电视机"><a href="#电视机" class="headerlink" title="电视机"></a>电视机</h2><p>没有手机和电脑的我们，电视机是最好的消遣。我家的电视机是索尼品牌的，从亲戚那里拿过来的，一直很耐用，直到快小学毕业才坏掉。</p><p>家里很长一段时间用的都是天线，好像也是快毕业才装的有线电视。天线时期只有珠江台是最稳定的，因此珠江台晚上7点钟的黄金时段，基本陪伴了我整个童年，比如生死十日、重案六组、甜蜜蜜等都还有印象，只不过我现在还在看的只剩下外来媳妇本地郎了。另外，那时候有个邻居，他爸妈有时候晚上要出去，就叫我陪他们儿子看电视，看的特别多的是星空台，比如犬夜叉、火影忍者等。不过，我对动漫好像不是特别感兴趣，喜欢看的是动画片，国产居多，比如虹猫蓝兔、果宝特攻、喜羊羊与灰太狼等，唉，都是时代的眼泪了。 不过现在看着猫和老鼠，还是能像以前那样放声大笑。我还记得 2008 年北京奥运会时，那期间珠江台每天早上会播放主题曲北京欢迎你，然后我基本每天都盼望看到并跟唱，换到现在，重温还是挺感动的，这么多明星一起合作的作品，现在很少看到了。</p><p>现在人们都围绕着手机和电脑，电视机的时代已经过去，一家人一起看电视的机会也跟着变少了。</p><h2 id="结束"><a href="#结束" class="headerlink" title="结束"></a>结束</h2><p>幸福的人用童年治愈一生，不幸的人用一生治愈童年。我很幸运有机会遇上一些好老师、好同学和好邻居，这是一段温暖的旅程，我会一直记得。</p><p>世间所有的相遇，都是久别重逢，有缘再见。</p><p>我未曾珍惜的，我不再拥有。</p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;&lt;a</summary>
        
      
    
    
    
    <category term="随笔" scheme="https://iwesley.top/categories/%E9%9A%8F%E7%AC%94/"/>
    
    
    <category term="随笔" scheme="https://iwesley.top/tags/%E9%9A%8F%E7%AC%94/"/>
    
  </entry>
  
  <entry>
    <title>安卓屏保调试2</title>
    <link href="https://iwesley.top/article/6c913ace/"/>
    <id>https://iwesley.top/article/6c913ace/</id>
    <published>2026-03-25T10:28:33.000Z</published>
    <updated>2026-03-25T13:33:57.000Z</updated>
    
    <content type="html"><![CDATA[<p>上一年为了研究屏保过程投屏，写了一篇文章：<a href="https://iwesley.top/article/98c55340/">安卓屏保调试 - Wesley’s Blog</a></p><p>今年为了做屏保广告又跟屏保打上交道了。</p><p>起初发现一台机器 dream 时间到了之后怎么也出不了屏保，直接把 <code>dumpsys power</code> 结果喂给 gpt，一下子就解决了，记录一下。</p><p><code>dumpsys power | grep -i mStayOnWhilePluggedInSetting</code> 这个结果显示 3，改成 0 就可以了。</p><h2 id="stay-on-while-plugged-in"><a href="#stay-on-while-plugged-in" class="headerlink" title="stay_on_while_plugged_in"></a>stay_on_while_plugged_in</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment">         * Whether we keep the device on while the device is plugged in.</span><br><span class="hljs-comment">         * Supported values are:</span><br><span class="hljs-comment">         * &lt;ul&gt;</span><br><span class="hljs-comment">         * &lt;li&gt;&#123;<span class="hljs-doctag">@code</span> 0&#125; to never stay on while plugged in&lt;/li&gt;</span><br><span class="hljs-comment">         * &lt;li&gt;&#123;<span class="hljs-doctag">@link</span> BatteryManager#BATTERY_PLUGGED_AC&#125; to stay on for AC charger&lt;/li&gt;</span><br><span class="hljs-comment">         * &lt;li&gt;&#123;<span class="hljs-doctag">@link</span> BatteryManager#BATTERY_PLUGGED_USB&#125; to stay on for USB charger&lt;/li&gt;</span><br><span class="hljs-comment">         * &lt;li&gt;&#123;<span class="hljs-doctag">@link</span> BatteryManager#BATTERY_PLUGGED_WIRELESS&#125; to stay on for wireless charger&lt;/li&gt;</span><br><span class="hljs-comment">         * &lt;li&gt;&#123;<span class="hljs-doctag">@link</span> BatteryManager#BATTERY_PLUGGED_DOCK&#125; to stay on for dock charger&lt;/li&gt;</span><br><span class="hljs-comment">         * &lt;/ul&gt;</span><br><span class="hljs-comment">         * These values can be OR-ed together.</span><br><span class="hljs-comment">         */</span><br><span class="hljs-meta">@Readable</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">String</span> <span class="hljs-variable">STAY_ON_WHILE_PLUGGED_IN</span> <span class="hljs-operator">=</span> <span class="hljs-string">&quot;stay_on_while_plugged_in&quot;</span>;<br></code></pre></td></tr></table></figure><h3 id="基础单值（对应特定的供电方式）"><a href="#基础单值（对应特定的供电方式）" class="headerlink" title="基础单值（对应特定的供电方式）"></a>基础单值（对应特定的供电方式）</h3><ul><li><strong>0</strong>：关闭状态（默认值）。无论连接什么电源，设备都会遵循常规的休眠和屏保倒计时。</li><li><strong>1</strong>：交流电 (AC)。只有在使用电源适配器（插在墙上）充电时，屏幕才保持常亮。对应底层常量 <code>BatteryManager.BATTERY_PLUGGED_AC</code>。</li><li><strong>2</strong>：USB。只有在连接到电脑或其他 USB 端口充电时，屏幕才保持常亮。对应底层常量 <code>BatteryManager.BATTERY_PLUGGED_USB</code>。</li><li><strong>4</strong>：无线充电 (Wireless)。只有在使用无线充电器时，屏幕才保持常亮。对应底层常量 <code>BatteryManager.BATTERY_PLUGGED_WIRELESS</code>。</li><li><strong>8</strong>：底座 (Dock)。插在专用底座上时保持常亮。对应底层常量 <code>BatteryManager.BATTERY_PLUGGED_DOCK</code>。</li></ul><p>由于采用了位掩码设计，可以将上述基础值相加（按位或操作 <code>|</code>），以同时支持多种情况：</p><ul><li><strong>3</strong> (<code>1 + 2</code>)：只要插着<strong>交流电或 USB</strong>，就不休眠。（最常见的组合值）</li><li><strong>7</strong> (<code>1 + 2 + 4</code>)：只要连着<strong>交流电、USB 或 无线充电</strong>中的任意一种，就不休眠。（通常被开发者用来表示“只要通电就不休眠”）</li></ul><p> 对于 Android TV 来说，由于它没有电池，通常被系统视为始终处于“AC 供电”状态。所以只要这个值包含了 <code>1</code>（比如设成了 <code>1</code>, <code>3</code> 或 <code>7</code>），TV 就永远不会进入 Dream 屏保了。  我碰到的就是这种情况。</p><h2 id="另外一些情况"><a href="#另外一些情况" class="headerlink" title="另外一些情况"></a>另外一些情况</h2><p>如果上面的值设置为 0 了，还是不行的话，可以继续排查：</p><p><code>dumpsys power | grep -E &quot;mWakefulness|Wake Locks|SCREEN_BRIGHT|FULL_WAKE|WindowManager&quot;</code></p><p>看Wake Locks size是不是 0：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs shell">YYT:/ #<br>YYT:/ # dumpsys power | grep -E &quot;mWakefulness|Wake Locks|SCREEN_BRIGHT|FULL_WAKE|WindowManager&quot;<br>  mWakefulness=Awake<br>  mWakefulnessChanging=false<br>  mScreenBrightnessOverrideFromWindowManager=NaN<br>  mUserActivityTimeoutOverrideFromWindowManager=-1<br>  mUserInactiveOverrideFromWindowManager=false<br>Wake Locks: size=0<br>  03-25 14:38:33.335 - 1000 - ACQ WindowManager/displayId:0 (screen-bright,on-after-release)<br>  03-25 14:38:35.528 - 1000 - REL WindowManager/displayId:0<br></code></pre></td></tr></table></figure><h3 id="UndimDetectorWakeLock"><a href="#UndimDetectorWakeLock" class="headerlink" title="UndimDetectorWakeLock"></a>UndimDetectorWakeLock</h3><p>在Android T版本中，系统新增了SCREEN_BRIGHT_WAKE_LOCK（UndimDetectorWakeLock）机制。当设备处于低亮度（dim）状态时，用户两次打断屏幕熄灭操作就会触发系统保持屏幕常亮10分钟。</p><p>比如：</p><ul><li><code>mKeepScreenOnEnabled = true</code></li><li><code>mKeepScreenOnForMillis = 10min</code></li><li><code>mUndimsRequired = 2</code></li><li><code>mMaxDurationBetweenUndimsMillis = 5min</code></li></ul><p>那就等于：</p><ol><li>屏幕先变暗一次。 </li><li>把它点亮，记第 1 次 undim。 </li><li>如果 <strong>5 分钟内</strong>又发生了第 2 次 undim，系统就判断“用户明显还在用”，于是<strong>额外保持亮屏 10 分钟</strong>。 </li><li>如果第 2 次发生在 5 分钟之后，那前面的计数作废，重新从 1 次开始算。</li></ol><p>这时候 screen_off_timeout 就会变得不准确了，以 <code>UndimDetectorWakeLock</code> 计时为准。</p><h2 id="调试命令"><a href="#调试命令" class="headerlink" title="调试命令"></a>调试命令</h2><p>查看屏保是否启用：</p><p><code>settings get secure screensaver_enabled</code></p><p>查看进入的屏保的时间：</p><p><code>settings get system screen_off_timeout</code></p><p>查看进入休眠的时间：</p><p><code>settings get secure sleep_timeout</code></p><p><code>sleep_timeout</code> 通常应比 <code>screen_off_timeout</code> 更长，不然设备会直接休眠而不是进屏保。</p><p> <code>dumpsys dreams</code>  </p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs shell">YYT:/ # dumpsys dreams<br>DREAM MANAGER (dumpsys dreams)<br><br>mCurrentDream=null<br>mForceAmbientDisplayEnabled=false<br>mDreamsOnlyEnabledForDockUser=false<br>mDreamsEnabledSetting=true<br>mDreamsActivatedOnDockByDefault=true<br>mDreamsActivatedOnChargeByDefault=true<br>mIsDocked=false<br>mIsCharging=true<br>mWhenToDream=3<br>mKeepDreamingWhenUnpluggingDefault=false<br>getDozeComponent()=null<br><br>Dreamland:<br>  mCurrentDream: null<br>  mSentStartBroadcast=false<br></code></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs shell">YYT:/ # settings list secure | grep screensaver<br>screensaver_activate_on_dock=1<br>screensaver_activate_on_sleep=1<br>screensaver_components=com.media/com.media.ScreensaverService<br>screensaver_default_component=com.google.android.apps.tv.dreamx/.service.Backdrop<br>screensaver_enabled=1<br>YYT:/ #<br>YYT:/ #<br>YYT:/ # settings list system | grep screen<br>dim_screen=1<br>lockscreen_sounds_enabled=1<br>screen_brightness=102<br>screen_brightness_mode=0<br>screen_off_timeout=30000<br></code></pre></td></tr></table></figure><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><p><a href="https://juejin.cn/post/7561264740879138870">Android14 用户两次打断息屏操作后，屏幕将会在10分钟内无法熄灭并持续点亮(关闭Android13新增的dim功能) - 掘金</a></p><p><a href="https://developer.android.com/develop/background-work/background-tasks/awake/screen-on?hl=zh-cn">使屏幕保持开启状态  | Background work  | Android Developers</a></p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;上一年为了研究屏保过程投屏，写了一篇文章：&lt;a href=&quot;https://iwesley.top/article/98c55340/&quot;&gt;安卓屏保调试 - Wesley’s</summary>
        
      
    
    
    
    <category term="AndroidFrameworkFeature" scheme="https://iwesley.top/categories/AndroidFrameworkFeature/"/>
    
    
    <category term="DreamManagerService" scheme="https://iwesley.top/tags/DreamManagerService/"/>
    
    <category term="Framework" scheme="https://iwesley.top/tags/Framework/"/>
    
    <category term="屏保" scheme="https://iwesley.top/tags/%E5%B1%8F%E4%BF%9D/"/>
    
  </entry>
  
  <entry>
    <title>Windows怎么方便查看AOSP代码</title>
    <link href="https://iwesley.top/article/1026a72d/"/>
    <id>https://iwesley.top/article/1026a72d/</id>
    <published>2026-03-24T13:53:41.000Z</published>
    <updated>2026-03-24T14:04:06.000Z</updated>
    
    <content type="html"><![CDATA[<p>在线查看源码一般可以使用<a href="https://cs.android.com/%E5%92%8Chttps://xrefandroid.com/">https://cs.android.com/和https://xrefandroid.com/</a> 。<br>但还是不如原生浏览的舒服。前者不能按分支来搜索代码，总是用最新的分支；后者，经常很慢，跳转不方便。后者在Windows上面打开建议使用Firefox，Chrome这些打开ams这种长文件容易导致电脑卡住不动。</p><p>接下来介绍一下怎么使用wsl2配置ASFP来浏览aosp代码，这样和windows联合使用比较方便。另外，wsl2还可以限制内存大小和重新调整磁盘大小，不是初始化后就绑定的。</p><p>之前已经介绍过在windows使用Linux的图形化界面了，这里就不重复展开了。可以参考：<a href="https://iwesley.top/article/89c7a079/">远程服务器运行Android Studio开发aosp源码 - Wesley’s Blog</a>和<a href="https://iwesley.top/article/3fc1a37/">在WSL2编译安卓13并在WSL2和windows运行 - Wesley’s Blog</a>。</p><p>建议电脑内存32G以上，还好我23年初配置了一台64G的台式机，现在内存价格上天了😭。</p><p>我目前安装的是Ubuntu20.04，分配了32G内存给它。安装好后，可以下载asfp给Ubuntu进行离线安装。</p><p><a href="https://developer.android.com/studio/platform">Android Studio for Platform  | Android Developers</a></p><p>AOSP源码可以到中科大镜像那里进行下载，建议先下载压缩包再同步<code>repo sync -c</code>。</p><h2 id="为什么使用-asfp"><a href="#为什么使用-asfp" class="headerlink" title="为什么使用 asfp"></a>为什么使用 asfp</h2><p>之前使用aidegen配合Android Studio和Clion来浏览代码，但现在使用aidegen有告警了，未来不再受支持了。建议切换到Android Studio for Platform (ASFP)。</p><p><a href="https://developer.android.com/studio/platform/tutorial?hl=zh-cn">ASfP 视频教程  | Android Studio for Platform  | Android Developers</a></p><blockquote><p>INFO: Please note that AIDEGen is no longer supported. We encourage you to use Android Studio for Platform (ASfP). Visit go&#x2F;asfp or google Android Studio for Platform for more information.</p><p>INFO: If you are sure the related modules and dependencies have been already built, please try to use command aidegen Settings -s to skip the building process.</p></blockquote><p>ASFP是什么？参考官方介绍：<a href="https://developer.android.com/studio/platform/intro?hl=zh-cn">探索 Android Studio for Platform  | Android Developers</a></p><p>ASfP 提供了一套全面的工具，这些工具针对平台开发特有的挑战进行了优化，超越了标准的 Android 应用开发。它与 AOSP 代码库和构建系统深度集成，可提供有助于加快开发流程的功能。</p><ul><li><strong>无缝 AOSP 集成</strong>：直接与 AOSP 源代码树和 Soong 构建系统（<code>Android.bp</code> 文件）配合使用。轻松同步和管理复杂的平台项目。</li><li><strong>智能代码编辑</strong>：利用 Kotlin、Java、C&#x2F;C++ 和 Rust 的高级代码补全、重构和分析功能，帮助您更快地编写高质量的代码。</li><li><strong>强大的调试功能</strong>：使用断点、变量检查和表达式求值等功能调试平台代码，包括 C&#x2F;C++ 和 Java。 详细了解<a href="https://developer.android.com/studio/platform/debug?hl=zh-cn">调试</a>。</li><li><strong>集成式测试</strong>：直接从 IDE 运行 <code>atest</code> 命令，以执行平台测试并查看结果。请参阅<a href="https://developer.android.com/studio/platform/test?hl=zh-cn">测试平台代码</a>。</li><li><strong>可自定义的项目设置</strong>：使用灵活的 <code>.asfp-project</code> YAML 文件微调项目范围和构建配置。详细了解<a href="https://developer.android.com/studio/platform/projects?hl=zh-cn">项目管理</a>。</li><li><strong>Rust 语言支持</strong>：在 AOSP 中为 Rust 开发提供核心功能支持。如需了解详情，请参阅 <a href="https://developer.android.com/studio/platform/projects/rust?hl=zh-cn">ASfP 中的 Rust 支持</a>。</li><li><strong>AI 赋能的辅助功能</strong>：使用 <a href="https://developer.android.com/gemini-in-android?hl=zh-cn">Android Studio 中的 Gemini</a> 生成代码、更新代码，以及在编辑器中获取开发问题的解答。</li></ul><p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260324215624703.png" alt="img"></p><h2 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h2><p>asfp同步过程闪退，大概率是因为内存不够。可以限制编译线程：<code>export NINJA_ARGS=&quot;-j8&quot; </code>，再打开ASFP应用。</p><p>或者增加编译配置，根据你电脑的配置进行设置</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">repo:</span> <span class="hljs-string">/home/wesley/aosp</span><br><span class="hljs-attr">lunch:</span> <span class="hljs-string">aosp_cf_x86_64_phone-trunk_staging-userdebug</span><br><span class="hljs-attr">directories:</span><br>  <span class="hljs-attr">include:</span><br>    <span class="hljs-bullet">-</span> <span class="hljs-string">frameworks</span><br>  <span class="hljs-attr">exclude:</span> []<br><span class="hljs-attr">modules:</span><br>  <span class="hljs-attr">include:</span> []<br>  <span class="hljs-attr">exclude:</span> []<br><span class="hljs-attr">test_sources:</span> []<br><span class="hljs-attr">other_languages:</span><br>  <span class="hljs-bullet">-</span> <span class="hljs-string">cpp</span><br><span class="hljs-attr">build_config:</span><br>  <span class="hljs-attr">flags:</span><br>    <span class="hljs-bullet">-</span> <span class="hljs-string">&quot;-j8&quot;</span><br>  <span class="hljs-attr">env:</span> &#123;&#125;<br></code></pre></td></tr></table></figure><p>如果是高分屏，可以在设置那里调大 UI 或者字体。</p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;在线查看源码一般可以使用&lt;a href=&quot;https://cs.android.com/%E5%92%8Chttps://xrefandroid.com/&quot;&gt;https://cs.android.com/和https://xrefandroid.com/&lt;/a&gt;</summary>
        
      
    
    
    
    <category term="Android Build System" scheme="https://iwesley.top/categories/Android-Build-System/"/>
    
    
    <category term="Android" scheme="https://iwesley.top/tags/Android/"/>
    
    <category term="aosp编译" scheme="https://iwesley.top/tags/aosp%E7%BC%96%E8%AF%91/"/>
    
  </entry>
  
  <entry>
    <title>远程服务器运行Android Studio开发aosp源码</title>
    <link href="https://iwesley.top/article/89c7a079/"/>
    <id>https://iwesley.top/article/89c7a079/</id>
    <published>2026-03-07T14:55:45.000Z</published>
    <updated>2026-03-07T15:36:34.000Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>好像很多人不知道服务器也可以轻松使用as和clion，还在使用si或者vscode ssh。特意写一篇教程。</p></blockquote><p>2019年去HW实习的时候，我发现他们工程师在用source insight开发aosp。2020年去另外一家公司上班的时候，发现用的也是source insight，但我感觉并不好用，特别是跳转和自动补全，优点可能就是Samba导入时不怎么卡。</p><p>然后开始尝试Android Studio，用idegen.sh生成 android.ipr，但通过Samba导入还是很慢，即使在android.iml删除了很多模块。公司的有线最高支持1000Mbps，慢也可能与这个有关，不知道10G网口连接服务器会不会好一些。</p><p>后来，我发现Linux远程服务器利用x11协议也可以跑gui，然后我就开始在上面安装了Android Studio(便携版)，开发变得方便多了，跳转和补全都很方便。</p><p>服务器内存大、磁盘访问没有损耗，可以直接打开android.ipr，但由于工程庞大，第一次还可能慢，所以这时候可以利用exclude功能把不需要的模块排除，可以加快速度。Project Strucure那里也可以管理，或者编辑android.iml。</p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260307231533749.png" alt="image.png" style="zoom:50%;" /><p>有时候可能刚打开git没法识别，导致没法追踪变更，可以自己配置。</p><h2 id="aidegen"><a href="#aidegen" class="headerlink" title="aidegen"></a>aidegen</h2><p>安卓10开始有aidegen了，更加方便了，开箱即用，配合as和clion直接打开对应的模块，比如打开设置，命令具体用法可以自己搜索。</p><p><code>aidegen Settings -i s -p  ~/android-studio -s</code></p><h2 id="调试system-server"><a href="#调试system-server" class="headerlink" title="调试system_server"></a>调试system_server</h2><p>服务器和安卓机器保持同一个网络，连接adb后可以直接打点调试。</p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260307231618459.png" alt="img" style="zoom:50%;" /><h2 id="界面模糊问题"><a href="#界面模糊问题" class="headerlink" title="界面模糊问题"></a>界面模糊问题</h2><p>x11里面也有一个dpi设置，但貌似没什么效果，还是保持auto吧。</p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260307231630134.png" alt="img" style="zoom:50%;" /><p>打开替代高dpi缩放行为，设置后重启应用，Android studio界面的外观和字体可以到Android studio设置里面按需调整，此时会变得清晰很多。</p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20260307231638077.png" alt="img" style="zoom: 67%;" /><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>windows有强大的mobaxterm，x11支持非常友好，macos上面好像就一个<a href="https://www.xquartz.org/">XQuartz</a>，不一定有用。</p><p>按某一个方向键可能会一直打字，建议不要使用中文键盘，微信输入法兼容性貌似会好点。</p><p>在Linux服务器安装好as或者asfp、clion就可以使用了。（tar便携版可以安装在自己home目录）</p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;blockquote&gt;
&lt;p&gt;好像很多人不知道服务器也可以轻松使用as和clion，还在使用si或者vscode ssh。特意写一篇教程。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;2019年去HW实习的时候，我发现他们工程师在用source</summary>
        
      
    
    
    
    <category term="Android Build System" scheme="https://iwesley.top/categories/Android-Build-System/"/>
    
    
    <category term="Android" scheme="https://iwesley.top/tags/Android/"/>
    
    <category term="aosp编译" scheme="https://iwesley.top/tags/aosp%E7%BC%96%E8%AF%91/"/>
    
  </entry>
  
  <entry>
    <title>withContext跨线程返回值为什么不需要volatile</title>
    <link href="https://iwesley.top/article/812f630/"/>
    <id>https://iwesley.top/article/812f630/</id>
    <published>2026-01-25T09:02:38.000Z</published>
    <updated>2026-03-07T15:09:38.000Z</updated>
    
    <content type="html"><![CDATA[<p>我们平常写协程代码时，如下所示，不需要什么<code>volatile</code>，就能获取正确的结果，那么协程是怎么保证我们的跨线程传递变量是安全的？需要从 happens-before 讲起。</p><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs kotlin">lifecycle.coroutineScope.launch &#123;<br>  <span class="hljs-keyword">var</span> a = <span class="hljs-number">50</span><br>  <span class="hljs-keyword">val</span> result = withContext(Dispatchers.IO) &#123;<br>    delay(<span class="hljs-number">3000</span>)<br>    a++<br>    <span class="hljs-number">55</span><br>  &#125;<br>  Log.e(TAG, <span class="hljs-string">&quot;onCreate result: <span class="hljs-variable">$result</span> a:<span class="hljs-variable">$a</span>&quot;</span>)<br>&#125;<br><br>lifecycle.coroutineScope.launch(Dispatchers.Default) &#123;<br>  <span class="hljs-keyword">var</span> b = <span class="hljs-number">50</span><br>  <span class="hljs-keyword">val</span> result = withContext(Dispatchers.IO) &#123;<br>    delay(<span class="hljs-number">3000</span>)<br>    b++<br>    <span class="hljs-number">55</span><br>  &#125;<br>  Log.e(TAG, <span class="hljs-string">&quot;onCreate result: <span class="hljs-variable">$result</span> b:<span class="hljs-variable">$b</span>&quot;</span>)<br>&#125;<br></code></pre></td></tr></table></figure><h2 id="happens-before原则"><a href="#happens-before原则" class="headerlink" title="happens-before原则"></a>happens-before原则</h2><p>main 入队 出队 </p><p>future 例子</p><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;我们平常写协程代码时，如下所示，不需要什么&lt;code&gt;volatile&lt;/code&gt;，就能获取正确的结果，那么协程是怎么保证我们的跨线程传递变量是安全的？需要从 happens-before 讲起。&lt;/p&gt;
&lt;figure class=&quot;highlight</summary>
        
      
    
    
    
    <category term="计算机基础" scheme="https://iwesley.top/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80/"/>
    
    
    <category term="Android" scheme="https://iwesley.top/tags/Android/"/>
    
    <category term="Java" scheme="https://iwesley.top/tags/Java/"/>
    
    <category term="Kotlin" scheme="https://iwesley.top/tags/Kotlin/"/>
    
  </entry>
  
  <entry>
    <title>脱糖魔法：为什么 java.time 在 Android 上还是会翻车？</title>
    <link href="https://iwesley.top/article/f9617ce3/"/>
    <id>https://iwesley.top/article/f9617ce3/</id>
    <published>2026-01-21T14:25:05.000Z</published>
    <updated>2026-01-21T16:13:36.000Z</updated>
    
    <content type="html"><![CDATA[<p>最近在写一个广告频控的功能，用 vibe coding 很快就开发完了，工具类引用了<code>java.time.*</code>，为了兼容旧安卓版本，需要启用脱糖，否则 IDE 会提示 api 的兼容性问题。项目的 AGP 版本是 8.0+，一开始运行没问题，但后面因为客户的工程是 AGP 4.0+，不愿意升级，所以要考虑兼容。由于在 agp 8.0+开发，要兼容好低版本，必须考虑第三方 SDK 的compileSdk、kotlin 和 AGP的版本要求，现在 maven 仓库居然不能直接查看 aar 的元数据，不能快速知晓这几个版本的要求，只能叫 AI 写个 gradle 版本 解析一下。坑都踩完后，发布 sdk 给客户，但客户 app 依赖sdk后，运行报错:<code>java.Lang.NoSuchMethodError: No static method ofInstant（Lj$/time/Instant;Lj$/time/ZoneId；）Lj$/time/LocalDate；in class Lj$/time/LocalDate</code>。究竟是为什么呢？分析之前先回顾一下语法糖和脱糖的知识点。</p><h2 id="语法糖和脱糖"><a href="#语法糖和脱糖" class="headerlink" title="语法糖和脱糖"></a>语法糖和脱糖</h2><p><strong>语法糖 &#x3D; 让我们写代码有更爽的写法</strong>，本质上不增加能力，只是更加优雅地写代码。</p><p>比如：</p><ul><li><code>lambda</code></li><li><code>forEach &#123; &#125;</code></li><li><code>接口默认方法</code></li><li><code>try-with-resources</code></li><li>Kotlin 的很多写法（<code>data class</code>、<code>when</code>、<code>?.let</code>）等等</li></ul><p><strong>脱糖（desugar）&#x3D; 把这些糖衣写法，改写成更基础、更原始的形式。</strong></p><h3 id="Android-里脱糖分两大类"><a href="#Android-里脱糖分两大类" class="headerlink" title="Android 里脱糖分两大类"></a>Android 里脱糖分两大类</h3><p>A. 语言特性脱糖（Language Desugaring）</p><p>让 <strong>“新语法特性”</strong> 在旧 Android 版本上也能跑。</p><p>比如：<code>lambda</code>写法。</p><p>B. Java 标准库 API 脱糖（Core Library Desugaring &#x2F; Library Desugaring）</p><p>旧 Android 系统里根本没有这些 API，或者缺很多方法，需要补上。</p><p>Android 的做法分为两步： </p><p><strong>步骤 1：打包一份“补齐的库”进 APK（desugar_jdk_libs）</strong> </p><p><strong>步骤 2：D8&#x2F;R8 把调用点路由到这份库上</strong><br> 也就是把对 <code>java.time.*</code> 的调用改写到 <code>j$.time.*</code>（内部替身包名） </p><img src="https://developer.android.com/static/studio/images/write/desugar_diagram.png?hl=zh-cn" alt="使用“desugar”字节码转换实现 Java 8 语言功能支持 " style="zoom:50%;" /><p>也就是打包 sdk 这一步是不会发生脱糖的，脱糖发生在 apk 编译。另外<code>sourceCompatibility</code>只能阻止新语法特性，不能阻止新 api 引入，这也能理解，因为新 api 是跟随安卓版本走的，虽然你用了 java 8 编写，但只要高版本系统支持，就可以引入。</p><p>对于 java 8 特性，需要 1.0+版本的库，对于 java 9+ 特性需要 2.0+的库。</p><figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs groovy">android &#123;<br>    compileOptions &#123;<br>        <span class="hljs-comment">// Flag to enable support for the new language APIs</span><br><br>        <span class="hljs-comment">// For AGP 4.1+</span><br>        isCoreLibraryDesugaringEnabled = <span class="hljs-literal">true</span><br>        <span class="hljs-comment">// For AGP 4.0</span><br>        <span class="hljs-comment">// coreLibraryDesugaringEnabled = true</span><br><br>        <span class="hljs-comment">// Sets Java compatibility to Java 8</span><br>        sourceCompatibility = JavaVersion.VERSION_1_8<br>        targetCompatibility = JavaVersion.VERSION_1_8<br>    &#125;<br>&#125;<br><br>dependencies &#123;<br>    <span class="hljs-comment">// For AGP 7.4+</span><br>    coreLibraryDesugaring(<span class="hljs-string">&quot;com.android.tools:desugar_jdk_libs:2.0.3&quot;</span>)<br>    <span class="hljs-comment">// For AGP 7.3</span><br>    <span class="hljs-comment">// coreLibraryDesugaring(&quot;com.android.tools:desugar_jdk_libs:1.2.3&quot;)</span><br>    <span class="hljs-comment">// For AGP 4.0 to 7.2</span><br>    <span class="hljs-comment">// coreLibraryDesugaring(&quot;com.android.tools:desugar_jdk_libs:1.1.9&quot;)</span><br>&#125;<br></code></pre></td></tr></table></figure><h2 id="问题分析"><a href="#问题分析" class="headerlink" title="问题分析"></a>问题分析</h2><p>频控代码里面有这么一句，显示 java 9 引入。</p><p><code>LocalDate.ofInstant(Instant.ofEpochMilli(nowMillis), zoneId)</code></p><p>参考 <a href="https://developer.android.com/studio/write/java8-support-table?hl=zh-cn">通过脱糖获得 Java 8 及更高版本 API  |  Android Studio  |  Android Developers</a> 里面可知，1.0 +的库是没有<code>LocalDate.ofInstant</code> 这个方法的，需要 2.0+的库才支持 java 9+ 特性： <a href="https://developer.android.com/studio/write/java11-nio-support-table?hl=zh-cn">通过脱糖提供的满足 Nio 规格要求的 Java 11 及更高版本 API  |  Android Studio  |  Android Developers</a>。所以客户的 agp 4.0+，不能正确脱糖导致没有生成<code>ofInstant</code>方法，运行报错：<code>java.Lang.NoSuchMethodError: No static method ofInstant（Lj$/time/Instant;Lj$/time/ZoneId；）Lj$/time/LocalDate；in class Lj$/time/LocalDate</code>。</p><p>这里注意，虽然脱糖不成功，但是里面的<code>LocalDate.ofInstant</code> 已经路由到新包名了，所以下面的写法也是被禁止的，即使安卓 14 支持，但是由于脱糖，无论成不成功，都会路由到新包名，所以在安卓 14 也会崩溃。但是你直接 run debug 版本的时候，会根据你的安卓设备不进行脱糖处理，看起来好像没问题，所以必须单独编译 apk 进行验证。</p><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs kotlin"><span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) &#123;<br>    LocalDate.ofInstant(Instant.ofEpochMilli(nowMillis), zoneId)<br>&#125; <span class="hljs-keyword">else</span> &#123;<br>    ZonedDateTime<br>        .ofInstant(Instant.ofEpochMilli(nowMillis), zoneId)<br>        .toLocalDate()<br>&#125; <br></code></pre></td></tr></table></figure><p>最后的修复方法是，按照 1.0 脱糖库的要求，不要使用 java 9+ api。</p><figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs groovy">ZonedDateTime.ofInstant(Instant.ofEpochMilli(nowMillis), zoneId).toLocalDate()<br></code></pre></td></tr></table></figure><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><p><a href="https://developer.android.com/studio/write/java8-support?hl=zh-cn#library-desugaring">使用 Java 8 语言功能和 API  |  Android Studio  |  Android Developers</a></p><p><a href="https://developer.android.com/studio/write/java8-support-table?hl=zh-cn">通过脱糖获得 Java 8 及更高版本 API  |  Android Studio  |  Android Developers</a></p><p><a href="https://developer.android.com/studio/write/java11-minimal-support-table?hl=zh-cn">通过脱糖提供的满足最低规格要求的 Java 11 及更高版本 API  |  Android Studio  |  Android Developers</a></p><p><a href="https://developer.android.com/studio/write/java11-nio-support-table?hl=zh-cn">通过脱糖提供的满足 Nio 规格要求的 Java 11 及更高版本 API  |  Android Studio  |  Android Developers</a></p><p><a href="https://developer.android.com/build/kotlin-support?hl=zh-cn">Kotlin 版本所需的 AGP、D8 和 R8 版本  |  Android Studio  |  Android Developers</a></p><p><a href="https://developer.android.com/build/tool-and-library-dependencies?hl=zh-cn">工具和库的相互依存关系  |  Android Studio  |  Android Developers</a></p><p><a href="https://developer.android.com/build/jdks?hl=zh-cn">Android build 中的 Java 版本  |  Android Studio  |  Android Developers</a></p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;最近在写一个广告频控的功能，用 vibe coding 很快就开发完了，工具类引用了&lt;code&gt;java.time.*&lt;/code&gt;，为了兼容旧安卓版本，需要启用脱糖，否则 IDE 会提示 api 的兼容性问题。项目的 AGP 版本是</summary>
        
      
    
    
    
    <category term="AppBuild" scheme="https://iwesley.top/categories/AppBuild/"/>
    
    
    <category term="Android" scheme="https://iwesley.top/tags/Android/"/>
    
    <category term="gradle" scheme="https://iwesley.top/tags/gradle/"/>
    
    <category term="Java" scheme="https://iwesley.top/tags/Java/"/>
    
  </entry>
  
  <entry>
    <title>豆包手机:戴着镣铐跳舞</title>
    <link href="https://iwesley.top/article/29834ee6/"/>
    <id>https://iwesley.top/article/29834ee6/</id>
    <published>2025-12-07T07:36:07.000Z</published>
    <updated>2025-12-07T11:44:32.000Z</updated>
    
    <content type="html"><![CDATA[<p>最近有一台手机很火，叫豆包 AI 手机，与中兴合作推出，好像三万台很快就抢没了，小黄鱼上面还要加价买。系统应该是由原锤子团队完成的，系统文件里面还残存着 Smartisan 字样，很可惜锤子没有坚持到 AI 爆发前夕，2020 年底发布完坚果 R2 后就没有手机产品了，如果再坚持 2 年，等到 2023 年初，可能会有不一样的局面。</p><p>虽然锤子不在了，但是我现在的手机用的还是锤子那套拟物化图标。</p><h2 id="豆包手机的特性"><a href="#豆包手机的特性" class="headerlink" title="豆包手机的特性"></a>豆包手机的特性</h2><p>除了拥有普通智能手机的功能外，最大的特性是将豆包 AI 大模型能力系统级集成到手机，可以理解用户复杂指令，跨 APP 执行任务，成为手机的GUI Agent。比如你喊一声“豆包豆包，帮我看下哪家咖啡店的冰美式便宜”，它可以乖乖打开饿了么、京东、美团等 APP，一家家看，一页页翻，帮你完成选择，还不打扰你当前页面操作，美滋滋。</p><p>平常我们在手机用的 ChatGPT、元宝这种 app 都只能局限于 APP 内操作，无法跨应用执行任务，也许可以借助无障碍服务等权限实现一些有限操作，但肯定不如系统级的豆包 AI 助手的。为什么呢？</p><p>豆包直接进了系统层，有系统签名，可以获取<code>android.permission.INJECT_EVENTS</code>等系统级权限，做到向屏幕注入任意触摸事件；配合 AI 定制按键实现全局唤醒，用起来更加方便；可以和本地模型打配合，例如屏幕截图、识别等可以本地化运行，解决隐私问题；可以借助虚拟屏幕实现 APP 在后台运行，不打断用户当前的操作等等。这些能力是第三方 AI 助手无法做到的。</p><p>那么手机厂商自己的 AI 手机助手呢？他们也可以做到上面的能力，例如之前荣耀在发布会上面就用 YOYO 点过奶茶。但是手机厂商很多没有自己研发基座模型，很多用的都是 DeepSeek 等开源模型，可能灵活和定制程度不如字节跳动自己开发的基座模型豆包，比如对复杂任务的拆解、执行等等。另外，字节作为一个外来者，会有更大胆的创新，没有束缚，非常规思维，或许能做到更加好用的 AI 手机，比如这一次豆包手机的轰动和出圈效应，是之前其他手机 AI 助手没有过的，就好像当初苹果作为一个创新者、开拓者打败诺基亚一样。</p><h2 id="踢到钢板"><a href="#踢到钢板" class="headerlink" title="踢到钢板"></a>踢到钢板</h2><p>有用户发现用豆包操作微信时，出现了问题：微信弹窗警告说登录环境异常，不让用了。后来阿里系相关应用也出现了操控失败的问题。针对网上议论，豆包手机官方很快发了声明，说非常重视用户的隐私，不会泄露用户隐私，重要步骤都需要得到用户的授权等等。针对 AI 操控手机的能力，限制了一部分使用场景，不能刷分、刷激励，限制金融类应用的使用，限制部分游戏类场景等等。</p><p>这时候我们发现，豆包手机的舞台并不是一个空地，而是一个到处拉了警戒线的广场。最开始能力太广，跳得很嗨，导致踩线的概率越高，这不就踢到微信这块“钢板”了吗。一直以来，市面有不少群控手机等黑产业，直接模拟人的操作，发广告，刷流量等等。微信等一直以来都是严厉打击这种群控模拟点击等行为的，会动态检测设备环境，比如是否是真的用户在操作，从而做出是否该限制用户使用的决定。豆包这种绕过人直接按指令操控微信的情况，大概率是触发了微信的反作弊检测。</p><p>当然，从技术上看，作为一个系统级应用，完全有能力做到不让微信发现，可以“更黑一点”，比如更隐蔽地注入事件、更像人类地操作，比如直接参考 <code>sendevent</code>直接向设备节点注入事件，随机化模拟点击等等。但这不是一个简单的技术问题，需要平衡好平台、用户和法律的关系，做一个自由放飞风筝的同时，线也要被牢牢扯住，要学会带着镣铐跳舞。因为 AI 手机本身没有什么天然权利去操控别人的 App，只有用户授权 + 平台规则允许 + 法律不反对三件事都站得住脚的时候，它的行为才算安全。</p><p>对于用户来说，肯定希望在自己授权和保护隐私的情况下，尽可能完成多的任务。比如比价、解决老年人不会用手机的困境等等。另外，AI 操作过程需要透明化，高危权限必须用户主动确认，不能擅作主张，绕过用户确认，包括删除数据等等。前段时间还有爆出过谷歌的编程工具直接删了用户的 D 盘的，这是一个严重事故啊。</p><p>对于平台来说，他当然不希望你批量点击，自动化刷数据，AI 答题等等，但用户会说这是我的权利，是我发出的指令，怎么就不能做呢？另外这也是一个入口之争，用户打开 App，看到的是它的首页、活动、推荐、广告等等，如果成为一个 AI 的插件，他的收益肯定会受影响。所以怎么分清用户正常需求和非法请求，解决矛盾，需要各方共同制定规则，不能因噎废食，一刀切，或许未来各个 APP 都有统一的 MCP 协议，AI 助手可以按需调用，不需要模拟点击了。</p><p>对于法律来说，它需要关心厂商有没有尽到安全保护和风险提示义务，有没有可能成为违法行为的帮凶。比如怎么界定 AI 操控 APP 是否触发入侵计算机罪？怎么保护用户的数据？ 如果 AI 没说清楚就把跨 App 的内容上传云端分析，或者被黑产拿去远程控制老人手机转账等等，这是绝对不行的。</p><h2 id="最后"><a href="#最后" class="headerlink" title="最后"></a>最后</h2><p>所有新技术涌现都肯定会有一段野蛮生长阶段，规则和监管就会显得滞后，当年苹果手机迫于运营商压力在我们这里还卖过不能用 WiFi 的机型呢，即使它支持这个功能，但现在每一个智能手机都支持 WiFi 了。</p><p>豆包手机这一波也类似，像是提前把未来的一角撕开给大家看了看：</p><ul><li><p>一边是人类的惰性与想象力：</p><blockquote><p>“要是手机能自己刷就好了。”</p></blockquote></li><li><p>一边是现实世界的边界与恐惧：</p><blockquote><p>“我不想我的钱、隐私和账号被一坨我看不见的东西接管。”</p></blockquote></li></ul><p>所以这几天我们才会看到这些画面:</p><ul><li>用户觉得“终于有点 AI 时代的感觉了”。</li><li>平台觉得“你这是往外挂的方向在滑”。</li><li>监管觉得“这玩意儿要是出事，后果很难收拾”。</li><li>厂商一边宣传未来，一边仓促地删功能、打补丁、发声明。</li></ul><p>GUI Agent AI 助手不会停止发展，但一定是带着镣铐跳舞的，而这副镣铐怎么铸、谁来管、谁有权说“不”，大概率会是未来几年里，AI 手机、超级 App、监管与用户一起磨出来的东西，规则和法律会变得更加完善，我们也能用上更安全可控的 GUI Agent AI 助手。</p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;最近有一台手机很火，叫豆包 AI 手机，与中兴合作推出，好像三万台很快就抢没了，小黄鱼上面还要加价买。系统应该是由原锤子团队完成的，系统文件里面还残存着 Smartisan 字样，很可惜锤子没有坚持到 AI 爆发前夕，2020 年底发布完坚果 R2</summary>
        
      
    
    
    
    <category term="随笔" scheme="https://iwesley.top/categories/%E9%9A%8F%E7%AC%94/"/>
    
    
    <category term="随笔" scheme="https://iwesley.top/tags/%E9%9A%8F%E7%AC%94/"/>
    
  </entry>
  
  <entry>
    <title>愿者上钩：再安全的手机也可能抵不过人性的考验</title>
    <link href="https://iwesley.top/article/1fbaaada/"/>
    <id>https://iwesley.top/article/1fbaaada/</id>
    <published>2025-11-30T11:31:18.000Z</published>
    <updated>2025-11-30T14:49:15.000Z</updated>
    
    <content type="html"><![CDATA[<p>我记得刚上大学那一会，在火车站，有一个陌生人说没钱坐车了，叫我给她10 块钱，我准备给的时候，她说其实是二十块，我说怎么又变成 20 了，她说我听错了，我突然感觉这是一个骗局就赶快走了。</p><p>多年以后，面对一个博主分享他妈妈被诈骗的故事，我会回想起来 2020 年那个遥远的夏天，即将走上工作岗位的我，遇到了来自“好友”的诈骗。</p><h3 id="在吗"><a href="#在吗" class="headerlink" title="在吗"></a>在吗</h3><p>大学毕业后，我在广州的同学那里住了几天。7 月 4 日那天下午，阳光灿烂，我独自出门拍身份证照片，在路上突然收到一位 QQ 好友发来的信息，“在吗？”。我也没多想，就回了一句，啥事。然后她开始讲自己“出事”了： 我微信登不上了，想把钱先转到你银行卡里，你用微信帮我把钱转给我表姐可以吗？</p><p>我感觉这个做法很奇怪，问为啥登不上？</p><p>说着说着，她突然给我发来了一个视频邀请。</p><p>我就点了接通。</p><p>视频那头画面出来了几秒不到，我朋友的脸闪了一下，然后视频就“嗖”一下断了。</p><p>这时候我开始警惕起来了。</p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20251130223716665.png" alt="IMG_20250813_124537" style="zoom:25%;" /><h3 id="语气不对的人"><a href="#语气不对的人" class="headerlink" title="语气不对的人"></a>语气不对的人</h3><p>这个朋友是我初中同学，虽然没有好到那种一起出去玩的程度，但一直以来都有联系，平时说话属于比较温柔和客气，相互尊敬。</p><p>结果那天她发过来的，有这种对话：</p><ul><li>“你在干嘛呢”</li><li>“我不知道啊”</li></ul><p>这种语气在这种对话场景我读起来就感觉很不耐烦，很不舒服，让我感觉不像她。</p><p>再加上那个“一闪而过”的视频，露脸时间短得离谱，像是拿着一张照片糊弄，让我确认是本人后就赶紧挂断了。</p><p>这些细节加在一起，整件事就越来越像一个骗局：照片是真的，就人不是那个人，是来骗钱的。</p><p>后来她对我的追问也没有回复，基本上可以确定她被盗号了。于是我赶紧放下 QQ，打开微信，给真正的好友发消息确认身份。很快就了解清楚她 QQ 被盗了，但不幸的是，她高中同桌最后还是被骗了一万，没有逃过骗子利用熟人情感作案的骗钱陷阱。</p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20251130222957455.jpg" alt="IMG_20250813_125152" style="zoom: 25%;" /><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20251130223106250.jpg" alt="IMG_20250813_125212" style="zoom: 25%;" /><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20251130223157339.jpg" alt="IMG_20250813_125232" style="zoom:25%;" /><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20251130224556899.jpg" alt="IMG_20251130_224511" style="zoom:25%;" /><h3 id="手机虽安全，但与人有关"><a href="#手机虽安全，但与人有关" class="headerlink" title="手机虽安全，但与人有关"></a>手机虽安全，但与人有关</h3><p>以安卓手机为例，它的安全其实挺全面的：</p><ul><li>每个 App 沙箱隔离，各住各的“号房”</li><li>运行时权限，读通讯录、看短信、开相机，都要弹个框问你一声</li><li>后面还有SELinux 在后面卡着各种访问，“该干啥干啥，不该干别想”</li></ul><p>但我同学的整个诈骗过程，貌似跟这些东西几乎一点关系都没有。</p><p>对方不需要：</p><ul><li>不需要提权</li><li>不需要越过沙箱</li><li>不需要突破 SELinux</li><li>不需要读我的短信、偷我的银行卡密码</li></ul><p>他只需要：</p><ul><li>一个盗来的 QQ 号</li><li>几张我朋友的照片</li><li>一段准备好的话术</li><li>再加上对这个头像背后的人天然的信任</li></ul><p>就足够了。</p><p>说明白点就是，即使现在的手机已经足够安全了，但最终还是要受控于人的，要看人性是否经得起考验。诈骗分子就是利用心理战术，玩人和人的游戏，利用熟人之间的情感羁绊，突破了人的边界防线，一步步将人引入陷阱，最后套取金钱，远走高飞。</p><h3 id="我为什么没有上当"><a href="#我为什么没有上当" class="headerlink" title="我为什么没有上当"></a>我为什么没有上当</h3><p>大概有这么几个点：</p><ol><li>作为一个理科生和经常网上冲浪的我来说，对这种网上钱财交易会事先保持多一份警惕。</li><li>我对这个朋友平时说话方式的记忆，她语气不对，乱用语气助词。</li><li>视频聊天那一下太刻意，闪一下真脸就挂断。</li><li>通过微信去核实，就是这么简单的一步换个渠道问一下本人，直接把骗局拆穿。</li></ol><p>而被骗的那位同学，很可能在那一刻：</p><ul><li>更相信照片和那几秒的视频</li><li>更相信“是同桌，她不会害我”</li><li>没有意识到自己可以换个渠道核实</li></ul><p>就这样，钱被骗走了，很可惜。</p><h3 id="尾声"><a href="#尾声" class="headerlink" title="尾声"></a>尾声</h3><p>再安全的手机也可能抵不过人性的考验，骗子很狡猾，洞悉人性的弱点，需要我们提高警惕，识别骗人套路。</p><p>骗局一般有两大类：</p><p><strong>陌生人骗局</strong>：主要打的是「钱袋子 + 对权威&#x2F;规则的恐惧」</p><p><strong>熟人骗局</strong>：主要打的是「人情 + 自我认同（我是个讲义气的人）」</p><p>前者靠的是话术和脚本，后者靠的是真实的头像、聊天记录，再加一点点愿意相信的部分。</p><p>来看一下 ChatGPT 的总结：</p><table><thead><tr><th>维度</th><th>陌生人骗局</th><th>熟人骗局（比如 QQ 好友那种）</th><th>背后心理学机制</th><th>大白话</th></tr></thead><tbody><tr><td><strong>初始警惕度</strong></td><td>默认当「不明链接」「骚扰电话」，警惕值偏高</td><td>默认当「自己人」，警惕值直接打折</td><td>内群体偏好、启发式判断</td><td>大脑偷懒：熟悉&#x3D;安全，不熟&#x3D;先防着点</td></tr><tr><td><strong>信任来源</strong></td><td>靠「官方身份」「权威」「福利诱惑」：客服、公检法、快递、中奖</td><td>靠「头像 + 昵称 + 聊天记录 + 共同回忆」</td><td>权威效应 vs 内群体偏好</td><td>陌生人要扮权威，熟人直接借壳你的朋友形象</td></tr><tr><td><strong>主要情绪按钮</strong></td><td>贪（优惠、返利、中奖）、怕（冻结、立案、罚款）</td><td>义气（朋友有难要帮）、愧疚（不帮是不是太绝）、怕伤感情</td><td>损失厌恶、互惠、社会角色期待</td><td>陌生人这边是「钱和安全」，熟人这边是「感情和人情」</td></tr><tr><td><strong>质疑成本</strong></td><td>质疑一句「你是不是骗子」，没啥心理包袱</td><td>质疑一句会觉得「我是不是太不信任他」「会不会伤人」</td><td>面子 &#x2F; 关系损失厌恶</td><td>钱和尴尬对打，很多人宁愿钱出问题，也不想当场翻脸</td></tr><tr><td><strong>大脑工作模式</strong></td><td>一开始还能稍微分析一下，常见套路会被识别</td><td>很容易直接切到情绪模式：朋友喊一声「救命」就先信了</td><td>系统一 &#x2F; 系统二（快思考 vs 慢思考）</td><td>陌生人会启动“慢一点想想”，熟人容易直接凭感觉拍板</td></tr><tr><td><strong>典型说服路径</strong></td><td>先立「权威&#x2F;规则」，再甩风险和好处</td><td>先立「关系」，再说「只有你能帮我」「我不敢找别人」</td><td>服从权威 vs 关系导向</td><td>一个靠「我是系统」，一个靠「我是你的人」</td></tr><tr><td><strong>是否愿意多验证一步</strong></td><td>挂电话 &#x2F; 打官方电话 &#x2F; 上网搜一下的概率相对高</td><td>换渠道去问本人、要语音&#x2F;视频的意愿明显更低</td><td>信息隔离、羞耻感</td><td>越熟越不好意思抽身去求证，感觉像是在“试探朋友”</td></tr><tr><td><strong>小请求→大请求</strong></td><td>直接开口要钱的多，被拒绝几率也高</td><td>先聊近况→讲惨状→情绪铺垫→再借钱，连续点头后更难说不</td><td>登门槛效应（foot-in-the-door）</td><td>你前面一直在扮“愿意帮忙的人”，最后关头很难突然变脸拒绝</td></tr><tr><td><strong>自我形象牵扯</strong></td><td>「我有没有被骗」为主</td><td>「我是不是个够义气的朋友」+「我怎么这么蠢」双重打击</td><td>自我认同、认知失调</td><td>为了维持“我是好朋友”的人设，你会给对方、也给自己各种理由</td></tr><tr><td><strong>上钩后感受</strong></td><td>多是愤怒 + 委屈：「骗子真坏」</td><td>背叛感 + 自责：「我看错人」「我是不是傻」「我不配有朋友」</td><td>内归因偏差</td><td>熟人局更伤，容易把问题全归到自己身上，创伤更深</td></tr><tr><td><strong>事后防御反应</strong></td><td>提防「某类电话&#x2F;链接」</td><td>容易演变成「谁借钱我都不信」「人都不可靠」</td><td>防御性悲观、过度泛化</td><td>陌生人骗局让你防套路，熟人骗局容易让你防所有人</td></tr></tbody></table><p>要对付陌生人骗局，重点是<strong>识别套路</strong>；<br>要对付熟人骗局，重点是<strong>给自己一点“核实的权利”</strong>。</p><p>首先要保障手机的安全，不要乱听陌生电话的指引，打开手机的电话识别功能，骚扰、诈骗等电话一律不接，开启运营商的高频骚扰电话拦截等等；不要乱下载软件，特别不要从非官方渠道下载软件，父母的手机要关闭非官方渠道下载安装功能，苹果这个做的比较好，要验证密码；不要随意打开短信里面的链接；设置好手机和 SIM 卡 PIN 密码；安卓手机不要交出电话、短信等读取权限，特别是无障碍权限，这相当于给诈骗分子掌握了控制手机的能力。</p><p>不过最重要的还是要回到我们自己身上，手机只是工具，我们才是手机的主人：</p><ol><li>所有熟人借钱，一律二次渠道确认：QQ 来的，就去微信；微信来的，就打电话。</li><li>能语音就不要只看文字，能视频就不要只看头像，如果对方死活不语音不视频，只打字还一直催，那危险系数直接拉满。</li><li>任何别告诉别人的，一律优先告诉别人，不管是别跟家人说、别跟同事说，这种话本身就很不对劲，骗子惯用伎俩。</li><li>再不转就来不及的钱，先拖一拖。能被“催一催”催走的，多半不是好事。</li><li>与钱有关的，都要事先提高警惕，默认是骗局，多和家人、朋友沟通。</li></ol><p>就这些小延迟、二次确认、沟通，可能比一堆看不见的安全设置，更能帮我们少掉几次坑，特别是要做好父母的工作，防止他们被骗。</p><p>希望在这个人与人的游戏中，没有愿者上钩的人。</p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;我记得刚上大学那一会，在火车站，有一个陌生人说没钱坐车了，叫我给她10 块钱，我准备给的时候，她说其实是二十块，我说怎么又变成 20 了，她说我听错了，我突然感觉这是一个骗局就赶快走了。&lt;/p&gt;
&lt;p&gt;多年以后，面对一个博主分享他妈妈被诈骗的故事，我会回想起来 2020</summary>
        
      
    
    
    
    <category term="随笔" scheme="https://iwesley.top/categories/%E9%9A%8F%E7%AC%94/"/>
    
    
    <category term="随笔" scheme="https://iwesley.top/tags/%E9%9A%8F%E7%AC%94/"/>
    
  </entry>
  
  <entry>
    <title>怎么在Apple Music听南京市民和升哥的歌</title>
    <link href="https://iwesley.top/article/20c98ff0/"/>
    <id>https://iwesley.top/article/20c98ff0/</id>
    <published>2025-11-26T11:13:31.000Z</published>
    <updated>2025-11-26T12:53:59.000Z</updated>
    
    <content type="html"><![CDATA[<p>我的 NAS 有他们的歌，刚开始用极音乐听，但真的不好用，竟然在电脑上面不能同步手机端的喜欢😅。</p><p>然后就开始在网上搜索解决办法：刚开始用 plex  ，结果一直显示 nas 加载失败，无奈继续探索。后面就发现了Navidrome 这个开源的音乐流媒体服务器，配合音流基本满足了我的需求。再加上 MusicTagWeb 可以刮削歌词，修复乱码信息等，可以愉快地听音乐了。但是有一个弊端，没有公网 IP 和内网穿透，没办法在外面听音乐。怎么办？</p><p>当然可以把音乐导入到手机，但是不方便。那么网盘呢？我是网易云音乐的会员，之前使用过它的云盘，但是不好用，没办法像在线音乐那样按歌手和专辑查看，还不能编辑音乐信息，而且有一些导入的音乐还不能点喜欢和收藏，不好用。</p><p>这两天发现 Apple Music 也可以导入本地音乐并在多端同步，使用起来还不错，能编辑歌曲信息，修改封面和导入歌词，点喜欢能和在线音乐一样收藏到歌单，下面是具体使用方法。</p><p>PS：有其他区 Apple Music 和 Spotify 的不需要这么折腾。。。。</p><h2 id="导入前"><a href="#导入前" class="headerlink" title="导入前"></a>导入前</h2><h3 id="导入前的设置"><a href="#导入前的设置" class="headerlink" title="导入前的设置"></a>导入前的设置</h3><p>如果你不希望本地音乐导入时被复制多一份，要去掉下面的勾选：添加到资料库时将文件拷贝到“媒体”文件夹</p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20251126193308052.png" alt="image-20251126193255494" style="zoom:50%;" /><p>编码选择 aac 就行，其他的可能兼容性不好，导致在线播放失败，参考：<a href="https://support.apple.com/zh-cn/guide/music/mus2965/mac">在 Mac 上的“音乐”中选取导入设置 - 官方 Apple 支持 (中国)</a></p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20251126193356362.png" alt="image-20251126193356289" style="zoom:50%;" /><h3 id="刮削"><a href="#刮削" class="headerlink" title="刮削"></a>刮削</h3><p>推荐使用<a href="https://xiers-organization.gitbook.io/music-tag-web">Music Tag Web</a>补充歌曲信息，但这个貌似不支持自定义歌词 api，所以如果是南京市民或者升哥等的话，用这个是拿不到信息的，可以使用<a href="https://www.mp3tag.de/en/">Mp3tag - the universal Tag Editor (ID3v2, MP4, OGG, FLAC, …)</a>，他的标签源有MusicBrainz和Discogs，可以补充完整。</p><h2 id="导入"><a href="#导入" class="headerlink" title="导入"></a>导入</h2><p>建议以专辑为单位导入，格式支持 MP3、AAC、WAV、M4A、AIFF、ALAC 等，FLAC 不支持：</p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20251126194255601.png" alt="image-20251126194255436" style="zoom:50%;" /><p>导入后可以在最近添加那里看到信息，如果没有，那就是音乐标签识别不成功，但可以在歌曲列表那里看到，一般没有识别的歌曲会放在列表最后，或者点击云端图标排序显示在前，可以自己手动批量修正歌曲的信息。但有时候需要退出一下音乐重新进入才能看到。</p><h2 id="同步"><a href="#同步" class="headerlink" title="同步"></a>同步</h2><p>手动触发更新云端资料库，左下角可以点击查看上传进度：</p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20251126194821210.png" alt="image-20251126194821153" style="zoom:50%;" /><p>等待同步成功之后，此时播放上传的音乐还是关联到本地路径的。因为 mac 的 Samba 太垃圾了，有时候会断连，所以如果你的音乐是从 nas 上传的，想脱离它时也能播放，需要先退出音乐账号，然后把歌曲列表清空，再登录时，会使用云端资源，这时候和 NAS 无关了。</p><p>注意：刚同步完成时，在线播放可能会很卡，因为此时的云端资源可能在海外，可以试着加速一下blobstore.apple.com，或者等待一天左右。我是刚开始很卡，一天后就能流畅播放了，可能此时 CDN 分发起效了。</p><h2 id="歌词"><a href="#歌词" class="headerlink" title="歌词"></a>歌词</h2><p>推荐使用<a href="https://github.com/MxIris-LyricsX-Project/LyricsX">LyricsX</a>，除了国内歌词源外，还有Musixmatch和LRCLIB，方便补充南京市民等歌曲的歌词信息。</p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20251126201719885.png" alt="image-20251126201719696" style="zoom:50%;" /><p>南京市民等歌曲的歌词信息可能会胡乱匹配，建议打开精确搜索，自动匹配可能失败，可以手动搜索，优先选择Musixmatch和LRCLIB 的信息，Musixmatch和LRCLIB 返回结果可能比较慢，可以多试试。</p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20251126201842449.png" alt="image-20251126201842390" style="zoom:50%;" /><p>确认对了之后，可以写入到 Apple Music，再同步一下资料库就可以在手机端看到了。</p><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20251126202327210.png" alt="image-20251126202327144" style="zoom:50%;" /><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20251126204442851.png" alt="image-20251126204442760" style="zoom:33%;" /><img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20251126203134042.jpg" alt="img" style="zoom:33%;" /><p>注意：Musixmatch 需要 userToken，可以参考：<a href="https://gist.github.com/TrueMyst/0461aea999e347182486934fd83a4cf9">☕ BeatPrints: Get your user token from MusixMatch</a></p><p>windows 用户可以试试：<a href="https://github.com/jayfunc/BetterLyrics">jayfunc&#x2F;BetterLyrics: An elegant and deeply customizable lyrics &amp; player app, built with WinUI3&#x2F;Win2D | 一款优雅且高度自定义的歌词&#x2F;播放器应用，基于 WinUI3&#x2F;Win2D 构建</a></p><h2 id="尾声"><a href="#尾声" class="headerlink" title="尾声"></a>尾声</h2><p>和菜头：世间有两样东西可以轻易地把一个房间填满，一样是光，另一样是音乐。</p><p>我每天起床后就会用手机把音乐投送到小爱同学，感谢音乐这么多年的陪伴。</p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;我的 NAS 有他们的歌，刚开始用极音乐听，但真的不好用，竟然在电脑上面不能同步手机端的喜欢😅。&lt;/p&gt;
&lt;p&gt;然后就开始在网上搜索解决办法：刚开始用 plex  ，结果一直显示 nas 加载失败，无奈继续探索。后面就发现了Navidrome</summary>
        
      
    
    
    
    <category term="数字生活指南" scheme="https://iwesley.top/categories/%E6%95%B0%E5%AD%97%E7%94%9F%E6%B4%BB%E6%8C%87%E5%8D%97/"/>
    
    
    <category term="随笔" scheme="https://iwesley.top/tags/%E9%9A%8F%E7%AC%94/"/>
    
    <category term="数字生活指南" scheme="https://iwesley.top/tags/%E6%95%B0%E5%AD%97%E7%94%9F%E6%B4%BB%E6%8C%87%E5%8D%97/"/>
    
  </entry>
  
  <entry>
    <title>安卓如何收敛自身以及第三方sdk日志</title>
    <link href="https://iwesley.top/article/62681a5f/"/>
    <id>https://iwesley.top/article/62681a5f/</id>
    <published>2025-11-22T12:28:55.000Z</published>
    <updated>2025-11-23T09:57:58.000Z</updated>
    
    <content type="html"><![CDATA[<p>安卓日志来源一般有自身 app 或者第三方 SDK，自己的比较容易归一化处理，优秀的 SDK 也会提供日志策略接口，但有一些喜欢直接用安卓的标准日志接口或者不能设置日志策略，这种就比较讨厌了，处理起来也比较麻烦。有两种办法：混淆时全部去掉或者 hook 系统日志接口。</p><h2 id="编译期“阉割”：混淆处理"><a href="#编译期“阉割”：混淆处理" class="headerlink" title="编译期“阉割”：混淆处理"></a>编译期“阉割”：混淆处理</h2><p>编译期“阉割”：配置R8&#x2F;Proguard 日志优化规则，直接把日志方法当空气处理：</p><figure class="highlight axapta"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs axapta"><span class="hljs-meta"># 要全局去掉-dontoptimize</span><br><span class="hljs-meta"># 去掉 SDK 的 debug/info 日志</span><br>-assumenosideeffects <span class="hljs-keyword">class</span> <span class="hljs-title class_">com</span>.xxx.sdk.<span class="hljs-keyword">internal</span>.SdkLog &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-built_in">int</span> d(...);<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-built_in">int</span> i(...);<br>     <span class="hljs-meta"># 不写 e(...)，保留错误日志</span><br>&#125;<br><br><span class="hljs-meta"># 去除全部log</span><br>-assumenosideeffects <span class="hljs-keyword">class</span> <span class="hljs-title class_">android</span>.util.Log &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> *** d(...);<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> *** v(...);<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> *** i(...);<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> *** e(...);<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> *** w(...);<br>&#125;<br><br><span class="hljs-meta"># 去除System.out.println();</span><br>-assumenosideeffects <span class="hljs-keyword">class</span> <span class="hljs-title class_">java</span>.io.PrintStream &#123; <br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> println(...); <br>&#125; <br><br></code></pre></td></tr></table></figure><p>这样的打击范围太大，出现问题时无法收集日志。</p><h2 id="hook系统日志打印接口"><a href="#hook系统日志打印接口" class="headerlink" title="hook系统日志打印接口"></a>hook系统日志打印接口</h2><p>下面介绍使用字节跳动的bhook和腾讯的xlog来处理日志：前者用来hook日志接口，后者用来储存日志。</p><h3 id="日志打印原理："><a href="#日志打印原理：" class="headerlink" title="日志打印原理："></a>日志打印原理：</h3><p>Android app层或framework层，通过调用Log&#x2F;Slog&#x2F;Rlog中的方法打印日志，接着通过JNI会调用到native层android_util_Log_println_native接口，最终通过liblog的__android_log_buf_write方法进行日志打印。</p><figure class="highlight livescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs livescript">__android_log_buf_write<br><br>  --&gt;__android_log_write_log_message<br><br>     --&gt;get_logger_function<span class="hljs-function"><span class="hljs-params">()</span></span><br><span class="hljs-function"></span><br><span class="hljs-function">        --&gt;</span>__android_log_logd_logger<br><br>           --&gt;write_to_log<br><br>              --&gt;LogdWrite<br></code></pre></td></tr></table></figure><p>如果只需要拦截app层或framework层，只需要拦截android_util_Log_println_native 所在的libandroid_runtime.so 即可，android_util_Log_println_native 调用了__android_log_buf_write 方法。</p><h3 id="实践"><a href="#实践" class="headerlink" title="实践"></a>实践</h3><p>参考：<a href="https://github.com/bytedance/bhook/blob/main/doc/quickstart.zh-CN.md">bhook&#x2F;doc&#x2F;quickstart.zh-CN.md at main · bytedance&#x2F;bhook</a></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&lt;jni.h&gt;</span></span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&lt;string&gt;</span></span><br><span class="hljs-comment">//#include &lt;android/log.h&gt;</span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&lt;bytehook.h&gt;</span></span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&quot;xlogger/android_xlog.h&quot;</span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> TAG <span class="hljs-string">&quot;wesley-jni&quot;</span></span><br><span class="hljs-comment">//#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG,  __VA_ARGS__);</span><br><span class="hljs-comment">//#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG,  __VA_ARGS__);</span><br><span class="hljs-comment">//#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG,  __VA_ARGS__);</span><br><br><span class="hljs-type">static</span> <span class="hljs-type">bool</span> g_consoleLogOpen = <span class="hljs-literal">false</span>;<br><span class="hljs-type">static</span> <span class="hljs-type">bool</span> g_saveToFile = <span class="hljs-literal">false</span>;<br><br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">android_log_buf_write_proxy</span><span class="hljs-params">(<span class="hljs-type">int</span> bufID, <span class="hljs-type">int</span> prio, <span class="hljs-type">const</span> <span class="hljs-type">char</span> *tag, <span class="hljs-type">const</span> <span class="hljs-type">char</span> *text)</span> </span>&#123;<br>    <span class="hljs-built_in">BYTEHOOK_STACK_SCOPE</span>();<br>    <span class="hljs-comment">//LOGE(&quot;hook  log&quot;)</span><br>    <span class="hljs-type">int</span> ret = <span class="hljs-number">0</span>;<br>    <span class="hljs-type">char</span> tag_buffer[<span class="hljs-number">50</span>];<br>    <span class="hljs-keyword">if</span> (g_consoleLogOpen) &#123;<br>        <span class="hljs-built_in">snprintf</span>(tag_buffer, <span class="hljs-built_in">sizeof</span>(tag_buffer), <span class="hljs-string">&quot;wesley-%s&quot;</span>, tag);<br>        ret = <span class="hljs-built_in">BYTEHOOK_CALL_PREV</span>(android_log_buf_write_proxy, bufID, prio, tag_buffer, text);<br>    &#125;<br>    <span class="hljs-keyword">if</span> (g_saveToFile) &#123;<br>        <span class="hljs-keyword">if</span> (prio &gt;= ANDROID_LOG_ERROR) &#123;<br>            <span class="hljs-built_in">XLOGE</span>(tag, <span class="hljs-string">&quot;%s&quot;</span>, text);<br>        &#125; <span class="hljs-keyword">else</span> &#123;<br>            <span class="hljs-built_in">XLOGI</span>(tag, <span class="hljs-string">&quot;%s&quot;</span>, text);<br>        &#125;<br>    &#125;<br>    <span class="hljs-keyword">return</span> ret;<br>&#125;<br><br><span class="hljs-comment">// 过滤器函数。返回 true 表示需要 hook 这个 so；返回 false 表示不需要 hook 这个 so。</span><br><span class="hljs-function"><span class="hljs-type">bool</span> <span class="hljs-title">hook_log_allow_filter</span><span class="hljs-params">(<span class="hljs-type">const</span> <span class="hljs-type">char</span> *caller_path_name, <span class="hljs-type">void</span> *arg)</span></span><br><span class="hljs-function"></span>&#123;<br>    <span class="hljs-comment">//if(nullptr != strstr(caller_path_name, &quot;liblog.so&quot;)) return true;</span><br><br>    <span class="hljs-comment">//android_util_Log_println_native 所在so</span><br>    <span class="hljs-keyword">if</span>(<span class="hljs-literal">nullptr</span> != <span class="hljs-built_in">strstr</span>(caller_path_name, <span class="hljs-string">&quot;libandroid_runtime.so&quot;</span>)) <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br><br>    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br>&#125;<br><br><span class="hljs-type">bytehook_stub_t</span> stub_of_android_log_buf_write = <span class="hljs-literal">nullptr</span>; <span class="hljs-comment">// hook 的存根，用于后续 unhook</span><br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">hook_logcat</span><span class="hljs-params">()</span> </span>&#123;<br>    <span class="hljs-comment">//__android_log_write</span><br>    <span class="hljs-comment">//bytehook_hook_all(nullptr, &quot;android_log_print_proxy&quot;, (void *) (my_log_print), nullptr,</span><br>     <span class="hljs-comment">//                 nullptr);</span><br><span class="hljs-comment">//    stub_of_android_log_buf_write = bytehook_hook_all(nullptr,</span><br><span class="hljs-comment">//                                                      &quot;__android_log_buf_write&quot;,</span><br><span class="hljs-comment">//                                                      (void *) (android_log_buf_write_proxy),</span><br><span class="hljs-comment">//                                                      nullptr,</span><br><span class="hljs-comment">//                                                      nullptr);</span><br>    stub_of_android_log_buf_write = <span class="hljs-built_in">bytehook_hook_partial</span>(<br>            hook_log_allow_filter,<br>            <span class="hljs-literal">nullptr</span>,<br>            <span class="hljs-literal">nullptr</span>,<br>            <span class="hljs-string">&quot;__android_log_buf_write&quot;</span>,<br>            <span class="hljs-built_in">reinterpret_cast</span>&lt;<span class="hljs-type">void</span> *&gt;(android_log_buf_write_proxy),<br>            <span class="hljs-literal">nullptr</span>,<br>            <span class="hljs-literal">nullptr</span>);<br>    <span class="hljs-keyword">if</span> (stub_of_android_log_buf_write == <span class="hljs-literal">nullptr</span>) &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;<br>    &#125;<br>    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>&#125;<br><br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">unhook_logcat</span><span class="hljs-params">()</span> </span>&#123;<br>    <span class="hljs-keyword">if</span> (stub_of_android_log_buf_write != <span class="hljs-literal">nullptr</span>) &#123;<br>        <span class="hljs-built_in">bytehook_unhook</span>(stub_of_android_log_buf_write);<br>        stub_of_android_log_buf_write = <span class="hljs-literal">nullptr</span>;<br>    &#125;<br>&#125;<br><br><br><span class="hljs-keyword">extern</span> <span class="hljs-string">&quot;C&quot;</span><br><span class="hljs-function">JNIEXPORT <span class="hljs-type">void</span> JNICALL</span><br><span class="hljs-function"><span class="hljs-title">Java_com_wesley_android_c_toolkit_NativeHelper_00024Companion_unhookLogcat</span><span class="hljs-params">(JNIEnv *env,</span></span><br><span class="hljs-params"><span class="hljs-function">                                                                         jobject thiz)</span> </span>&#123;<br>    <span class="hljs-built_in">XLOGE</span>(TAG, <span class="hljs-string">&quot;unhook_logcat&quot;</span>);<br>    <span class="hljs-built_in">unhook_logcat</span>();<br>&#125;<br><br><span class="hljs-keyword">extern</span> <span class="hljs-string">&quot;C&quot;</span><br><span class="hljs-function">JNIEXPORT jboolean JNICALL</span><br><span class="hljs-function"><span class="hljs-title">Java_com_wesley_android_c_toolkit_NativeHelper_00024Companion_hookLogcat</span><span class="hljs-params">(JNIEnv *env, jobject thiz,</span></span><br><span class="hljs-params"><span class="hljs-function">                                                                       jboolean console_log_open, jboolean save_to_file)</span> </span>&#123;<br>    <span class="hljs-built_in">XLOGE</span>(TAG,<span class="hljs-string">&quot;hook_logcat&quot;</span>);<br>    g_consoleLogOpen = (console_log_open == JNI_TRUE);<br>    g_saveToFile = (save_to_file == JNI_TRUE);<br>    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">hook_logcat</span>() == <span class="hljs-number">0</span>) &#123;<br>        <span class="hljs-keyword">return</span> JNI_TRUE;<br>    &#125;<br>    <span class="hljs-keyword">return</span> JNI_FALSE;<br>&#125;<br></code></pre></td></tr></table></figure><p>app 层</p><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs kotlin"><span class="hljs-keyword">package</span> com.wesley.android.c.toolkit<br><br><span class="hljs-keyword">import</span> android.util.Log<br><span class="hljs-keyword">import</span> com.bytedance.android.bytehook.ByteHook<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">NativeHelper</span> &#123;<br><br>    <span class="hljs-keyword">companion</span> <span class="hljs-keyword">object</span> &#123;<br>        <span class="hljs-keyword">init</span> &#123;<br>            <span class="hljs-keyword">val</span> ret = ByteHook.<span class="hljs-keyword">init</span>()<br>            Log.e(<span class="hljs-string">&quot;ByteHook&quot;</span>, <span class="hljs-string">&quot;init ret: <span class="hljs-variable">$ret</span>&quot;</span>)<br>            System.loadLibrary(<span class="hljs-string">&quot;toolkit&quot;</span>)<br>        &#125;<br>        <span class="hljs-keyword">external</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">hookLogcat</span><span class="hljs-params">(consoleLogOpen: <span class="hljs-type">Boolean</span> = <span class="hljs-literal">true</span>, saveToFile: <span class="hljs-type">Boolean</span> = <span class="hljs-literal">true</span>)</span></span>: <span class="hljs-built_in">Boolean</span><br>        <span class="hljs-keyword">external</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">unhookLogcat</span><span class="hljs-params">()</span></span><br><br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><p>完整代码参考：<a href="https://github.com/wesley666/AndroidToolkit">wesley666&#x2F;AndroidToolkit: AndroidToolkit</a></p><p>运行 app 后可以看到日志 tag 加上了前缀 wesley，测试环境：小米 13，安卓 15。</p><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><p><a href="https://blog.csdn.net/feelabclihu/article/details/134213379">Android logd日志简介及典型案例分析</a></p><p><a href="https://juejin.cn/post/6905368512001556487">深入理解安卓日志系统（logcat &#x2F; liblog &#x2F; logd</a></p><p><a href="https://juejin.cn/post/7311167216728424463">Android帝国之日志系统–logd、logcat</a></p><p><a href="https://gityuan.com/2018/01/27/android-log/">Android logd日志原理 - Gityuan博客</a></p><p><a href="https://juejin.cn/post/7393746524473901119">Android日志是如何输出的：Log.d经历了什么</a></p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;安卓日志来源一般有自身 app 或者第三方 SDK，自己的比较容易归一化处理，优秀的 SDK 也会提供日志策略接口，但有一些喜欢直接用安卓的标准日志接口或者不能设置日志策略，这种就比较讨厌了，处理起来也比较麻烦。有两种办法：混淆时全部去掉或者 hook</summary>
        
      
    
    
    
    <category term="Android" scheme="https://iwesley.top/categories/Android/"/>
    
    
    <category term="Android" scheme="https://iwesley.top/tags/Android/"/>
    
    <category term="AndroidUtils" scheme="https://iwesley.top/tags/AndroidUtils/"/>
    
  </entry>
  
  <entry>
    <title>安卓如何每次重启开机后只执行一次代码</title>
    <link href="https://iwesley.top/article/ae07f8e0/"/>
    <id>https://iwesley.top/article/ae07f8e0/</id>
    <published>2025-11-09T11:06:34.000Z</published>
    <updated>2025-11-09T11:53:57.000Z</updated>
    
    <content type="html"><![CDATA[<p>安卓如何每次重启开机后只执行一次代码：</p><p>方法一、开机广播</p><p>比较普遍的一个方法，但可能接收延迟或者被禁止接收。</p><p>方法二、设置一个非 persist 属性作为标记，重启后系统自动清除</p><p>受 selinux 管控，第三方应用无权限执行。</p><p>方法三、使用&#x2F;proc&#x2F;sys&#x2F;kernel&#x2F;random&#x2F;boot_id 作为标记</p><p>相当于内核准备的一张 <strong>「本次开机身份证」</strong>。 </p><ul><li><strong>每次重启都会变化一次</strong></li><li><strong>在同一次开机过程中是稳定不变的</strong></li></ul><p>非常适合作为标记</p><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><code class="hljs kotlin"><span class="hljs-keyword">private</span> <span class="hljs-keyword">const</span> <span class="hljs-keyword">val</span> TAG = <span class="hljs-string">&quot;BootUtil&quot;</span><br><span class="hljs-keyword">private</span> <span class="hljs-keyword">const</span> <span class="hljs-keyword">val</span> PREF = <span class="hljs-string">&quot;boot_util_prefs&quot;</span><br><br><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">current</span><span class="hljs-params">(context: <span class="hljs-type">Context</span>)</span></span>: String &#123;<br>    kotlin.runCatching &#123;<br>        <span class="hljs-keyword">val</span> text = File(<span class="hljs-string">&quot;/proc/sys/kernel/random/boot_id&quot;</span>).readText().trim()<br>        <span class="hljs-keyword">if</span> (text.isNotEmpty()) <span class="hljs-keyword">return</span> text<br>    &#125;<br>    kotlin.runCatching &#123;<br>        <span class="hljs-keyword">val</span> cnt = Settings.Global.getInt(context.contentResolver, Settings.Global.BOOT_COUNT)<br>        <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;boot_count_<span class="hljs-variable">$cnt</span>&quot;</span><br>    &#125;<br>    <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;unknown_boot&quot;</span><br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">runOnce</span><span class="hljs-params">(context: <span class="hljs-type">Context</span>, block: () -&gt; <span class="hljs-type">Unit</span>)</span></span> &#123;<br>    <span class="hljs-keyword">val</span> marker = current(context).also &#123;<br>        Log.d(TAG, <span class="hljs-string">&quot;current boot marker: <span class="hljs-variable">$it</span>&quot;</span>)<br>    &#125;<br>    <span class="hljs-keyword">val</span> prefs = context.getSharedPreferences(PREF, Context.MODE_PRIVATE)<br>    <span class="hljs-keyword">val</span> doneKey = <span class="hljs-string">&quot;boot_once_<span class="hljs-variable">$marker</span>&quot;</span><br>    <span class="hljs-keyword">val</span> done = prefs.getBoolean(doneKey, <span class="hljs-literal">false</span>)<br>    <span class="hljs-keyword">if</span> (!done) &#123;<br>        block()<br>        prefs.edit &#123;<br>            clear()<br>            putBoolean(doneKey, <span class="hljs-literal">true</span>)<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;安卓如何每次重启开机后只执行一次代码：&lt;/p&gt;
&lt;p&gt;方法一、开机广播&lt;/p&gt;
&lt;p&gt;比较普遍的一个方法，但可能接收延迟或者被禁止接收。&lt;/p&gt;
&lt;p&gt;方法二、设置一个非 persist 属性作为标记，重启后系统自动清除&lt;/p&gt;
&lt;p&gt;受 selinux</summary>
        
      
    
    
    
    <category term="Android" scheme="https://iwesley.top/categories/Android/"/>
    
    
    <category term="Android" scheme="https://iwesley.top/tags/Android/"/>
    
    <category term="AndroidUtils" scheme="https://iwesley.top/tags/AndroidUtils/"/>
    
  </entry>
  
  <entry>
    <title>基于Binder的4种RPC调用</title>
    <link href="https://iwesley.top/article/f037b587/"/>
    <id>https://iwesley.top/article/f037b587/</id>
    <published>2025-10-03T13:50:23.000Z</published>
    <updated>2025-10-05T08:04:53.000Z</updated>
    
    <content type="html"><![CDATA[<p>基于Binder的4种RPC调用一般有AIDL、Messenger、借助 intent 传递 messenger 和 基于 contentprovider 的 call</p><p>AIDL 和Messenger 比较常见了，可以参考：<a href="https://developer.android.com/develop/background-work/services/bound-services?hl=zh-cn">绑定服务概览  |  Background work  |  Android Developers</a></p><p>这里只讨论后面两种情况，代码链接：<a href="https://github.com/wesley666/BinderRPC">https://github.com/wesley666/BinderRPC</a></p><h2 id="借助-intent-传递-messenger"><a href="#借助-intent-传递-messenger" class="headerlink" title="借助 intent 传递 messenger"></a>借助 intent 传递 messenger</h2><p>应用场景：比如授权弹窗需要借助另外一个进程或者组件完成，比如小米 adb 安装应用时的弹窗，安装流程是 system_server 完成的，但安全校验弹窗是安全中心负责的，方便解耦。</p><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br></pre></td><td class="code"><pre><code class="hljs kotlin"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Test</span> &#123;<br>    <span class="hljs-keyword">companion</span> <span class="hljs-keyword">object</span> &#123;<br>        <span class="hljs-keyword">private</span> <span class="hljs-keyword">const</span> <span class="hljs-keyword">val</span> TAG = <span class="hljs-string">&quot;TestIntentRPC&quot;</span><br>    &#125;<br><br>    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">testServer</span><span class="hljs-params">(context: <span class="hljs-type">Context</span>)</span></span> &#123;<br>        <span class="hljs-keyword">val</span> messenger = TestMessenger()<br>        <span class="hljs-keyword">val</span> intent = Intent()<br>        intent.`<span class="hljs-keyword">package</span>` = context.packageName<br>        intent.action = <span class="hljs-string">&quot;android.intent.action.AUTHORIZE&quot;</span><br>        <span class="hljs-keyword">val</span> bundle = Bundle().apply &#123;<br>            putValue(MESSENGER_KEY, messenger)<br>        &#125;<br>        intent.apply &#123;<br>            addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP)<br>            putExtra(ACTIVITY_INTENT_KEY, bundle)<br>        &#125;<br>        context.startActivity(intent)<br>        synchronized(messenger.lock) &#123;<br>            <span class="hljs-keyword">while</span> (!messenger.finished) &#123;<br>                <span class="hljs-keyword">try</span> &#123;<br>                    messenger.lock.wait(<span class="hljs-number">10</span> * <span class="hljs-number">1000L</span>)<br>                    messenger.finished = <span class="hljs-literal">true</span><br>                &#125; <span class="hljs-keyword">catch</span> (e: InterruptedException) &#123;<br>                    e.printStackTrace()<br>                &#125;<br>            &#125;<br>        &#125;<br>        Log.e(TAG, <span class="hljs-string">&quot;testServer messenger.result: <span class="hljs-subst">$&#123;messenger.result&#125;</span>&quot;</span>)<br>    &#125;<br><br>    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">testClient</span><span class="hljs-params">(intent: <span class="hljs-type">Intent</span>?)</span></span> &#123;<br>        <span class="hljs-keyword">var</span> iBinder: IBinder? = <span class="hljs-literal">null</span><br>        <span class="hljs-keyword">var</span> messenger: IMessenger? = <span class="hljs-literal">null</span><br>        intent?.getBundleExtra(ACTIVITY_INTENT_KEY)?.apply &#123;<br>            iBinder = getBinderValue(MESSENGER_KEY)<br>        &#125;<br>        iBinder?.let &#123;<br>            messenger = IMessenger.Stub.asInterface(it)<br>        &#125;<br>        messenger?.let &#123;<br>            <span class="hljs-keyword">val</span> message = Message()<br>            message.what = <span class="hljs-number">99</span><br>            it.send(message)<br>        &#125;<br><br>    &#125;<br><br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">inner</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">TestMessenger</span> : <span class="hljs-type">IMessenger.Stub</span>() &#123;<br>        <span class="hljs-meta">@Volatile</span><br>        <span class="hljs-keyword">var</span> finished: <span class="hljs-built_in">Boolean</span> = <span class="hljs-literal">false</span><br>        <span class="hljs-keyword">var</span> result: <span class="hljs-built_in">Int</span> = <span class="hljs-number">0</span><br>        <span class="hljs-keyword">val</span> lock = Object()<br><br>        <span class="hljs-meta">@SuppressLint(<span class="hljs-string">&quot;RethrowRemoteException&quot;</span>, <span class="hljs-string">&quot;VisiblySynchronized&quot;</span>, <span class="hljs-string">&quot;MissingNullability&quot;</span>)</span><br>        <span class="hljs-meta">@Throws(</span><br><span class="hljs-meta">            RemoteException::class</span><br><span class="hljs-meta">        )</span><br>        <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">send</span><span class="hljs-params">(message: <span class="hljs-type">Message</span>)</span></span> &#123;<br>            synchronized(lock) &#123;<br>                Log.i(TAG, <span class="hljs-string">&quot;onAuthCheck send result: <span class="hljs-subst">$&#123;message.what&#125;</span>&quot;</span>)<br>                <span class="hljs-keyword">this</span>.finished = <span class="hljs-literal">true</span><br>                <span class="hljs-keyword">this</span>.result = message.what<br>                lock.notifyAll()<br>            &#125;<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><p>framework 的代码可以借助IMessenger.Stub，app的代码可以自定义IMessenger</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@SuppressLint(&#123;&quot;RawAidl&quot;, &quot;CallbackMethodName&quot;, &quot;MissingNullability&quot;, &quot;RethrowRemoteException&quot;&#125;)</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">TestCallback</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">IMessenger</span>.Stub &#123;<br>        <span class="hljs-type">boolean</span> finished;<br>        String msg;<br>        <span class="hljs-type">int</span> result;<br><br>        <span class="hljs-meta">@SuppressLint(&#123;&quot;RethrowRemoteException&quot;, &quot;VisiblySynchronized&quot;, &quot;MissingNullability&quot;&#125;)</span><br>        <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">send</span><span class="hljs-params">(<span class="hljs-meta">@NonNull</span> Message message)</span> <span class="hljs-keyword">throws</span> RemoteException &#123;<br>            <span class="hljs-keyword">synchronized</span> (<span class="hljs-built_in">this</span>) &#123;<br>                <span class="hljs-built_in">this</span>.finished = <span class="hljs-literal">true</span>;<br>                <span class="hljs-built_in">this</span>.result = message.what;<br>                <span class="hljs-type">Bundle</span> <span class="hljs-variable">data</span> <span class="hljs-operator">=</span> message.getData();<br>                <span class="hljs-keyword">if</span> (data != <span class="hljs-literal">null</span>) &#123;<br>                    <span class="hljs-built_in">this</span>.msg = data.getString(<span class="hljs-string">&quot;msg&quot;</span>);<br>                &#125;<br>                notifyAll();<br>            &#125;<br>        &#125;<br>    &#125;<br></code></pre></td></tr></table></figure><h2 id="基于-contentprovider-的-call-方法"><a href="#基于-contentprovider-的-call-方法" class="headerlink" title="基于 contentprovider 的 call 方法"></a>基于 contentprovider 的 call 方法</h2><p>应用场景：比如需要同步 RPC 调用，aidl 是异步绑定的；新增或者删减方法更加方便，aidl 需要严格的方法定义顺序。</p><p>比如Settings.Secure.putInt()本质上就是利用了call方法进行rpc，可以参考：</p><p><a href="https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/core/java/android/provider/Settings.java?q=symbol:%5Cbandroid.provider.Settings.NameValueCache.putStringForUser%5Cb%20case:yes">frameworks&#x2F;base&#x2F;core&#x2F;java&#x2F;android&#x2F;provider&#x2F;Settings.java</a></p><p><a href="https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java?q=symbol:%5Cbcom.android.providers.settings.SettingsProvider.call%5Cb%20case:yes">frameworks&#x2F;base&#x2F;packages&#x2F;SettingsProvider&#x2F;src&#x2F;com&#x2F;android&#x2F;providers&#x2F;settings&#x2F;SettingsProvider.java</a></p><p>定义服务端：contentprovider，call里面也可以增加鉴权等</p><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs kotlin"><span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">call</span><span class="hljs-params">(method: <span class="hljs-type">String</span>, arg: <span class="hljs-type">String</span>?, extras: <span class="hljs-type">Bundle</span>?)</span></span>: Bundle? &#123;<br>    <span class="hljs-keyword">if</span> (ProviderHelper.CALL_FUNCTION == method &amp;&amp; extras != <span class="hljs-literal">null</span> &amp;&amp; arg != <span class="hljs-literal">null</span>) &#123;<br>        <span class="hljs-keyword">return</span> funMap.callFun(arg, extras)<br>    &#125;<br>    <span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.call(method, arg, extras)<br>&#125;<br></code></pre></td></tr></table></figure><p>服务端方法定义</p><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><code class="hljs kotlin"><span class="hljs-keyword">class</span> <span class="hljs-title class_">FunMap</span>(<span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> context: Context) &#123;<br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> functions: HashMap&lt;String, (Bundle) -&gt; Bundle?&gt; = HashMap()<br><br>    <span class="hljs-keyword">init</span> &#123;<br>        <span class="hljs-keyword">init</span>()<br>    &#125;<br><br>    <span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">init</span><span class="hljs-params">()</span></span> &#123;<br>        functions[MethodDef.SAY_HELLO] = &#123; bundle -&gt;<br>            Log.i(TAG, <span class="hljs-string">&quot;say hello from <span class="hljs-subst">$&#123;bundle.getString(ProviderHelper.KEY_ONE)&#125;</span>&quot;</span>)<br>            <span class="hljs-literal">null</span><br>        &#125;<br>        functions[MethodDef.GET_NAME] = <span class="hljs-symbol">lambda@</span>&#123;<br>            <span class="hljs-keyword">return</span><span class="hljs-symbol">@lambda</span> Bundle().apply &#123;<br>                putString(ProviderHelper.KEY_RET, context.packageName)<br>            &#125;<br>        &#125;<br>    &#125;<br><br><br>    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">callFun</span><span class="hljs-params">(methodName: <span class="hljs-type">String</span>, bundle: <span class="hljs-type">Bundle</span>)</span></span>: Bundle &#123;<br>        <span class="hljs-keyword">return</span> functions[methodName]?.invoke(bundle) ?: Bundle()<br>    &#125;<br><br><br>    <span class="hljs-keyword">companion</span> <span class="hljs-keyword">object</span> &#123;<br>        <span class="hljs-keyword">private</span> <span class="hljs-keyword">const</span> <span class="hljs-keyword">val</span> TAG = <span class="hljs-string">&quot;ProviderFunMap&quot;</span><br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><p>公共方法</p><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><code class="hljs kotlin"><span class="hljs-keyword">object</span> MethodDef &#123;<br>    <span class="hljs-keyword">const</span> <span class="hljs-keyword">val</span> SAY_HELLO = <span class="hljs-string">&quot;sayHello&quot;</span><br>    <span class="hljs-keyword">const</span> <span class="hljs-keyword">val</span> GET_NAME = <span class="hljs-string">&quot;getName&quot;</span><br>&#125;<br><br><span class="hljs-meta">@SuppressLint(<span class="hljs-string">&quot;StaticFieldLeak&quot;</span>)</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ProviderHelper</span>(<span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> context: Context, <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> uriPath: String) &#123;<br>    <span class="hljs-keyword">companion</span> <span class="hljs-keyword">object</span> &#123;<br>        <span class="hljs-keyword">const</span> <span class="hljs-keyword">val</span> KEY_ONE: String = <span class="hljs-string">&quot;key_one&quot;</span><br>        <span class="hljs-keyword">const</span> <span class="hljs-keyword">val</span> KEY_TWO: String = <span class="hljs-string">&quot;key_two&quot;</span><br>        <span class="hljs-keyword">const</span> <span class="hljs-keyword">val</span> KEY_THREE: String = <span class="hljs-string">&quot;key_three&quot;</span><br>        <span class="hljs-keyword">const</span> <span class="hljs-keyword">val</span> KEY_FOUR: String = <span class="hljs-string">&quot;key_four&quot;</span><br>        <span class="hljs-keyword">const</span> <span class="hljs-keyword">val</span> KEY_FIVE: String = <span class="hljs-string">&quot;key_five&quot;</span><br>        <span class="hljs-keyword">const</span> <span class="hljs-keyword">val</span> KEY_RET: String = <span class="hljs-string">&quot;ret&quot;</span><br>        <span class="hljs-keyword">const</span> <span class="hljs-keyword">val</span> CALL_FUNCTION: String = <span class="hljs-string">&quot;callFunction&quot;</span><br>        <span class="hljs-keyword">const</span> <span class="hljs-keyword">val</span> TAG: String = <span class="hljs-string">&quot;ProviderHelper&quot;</span><br>    &#125;<br><br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> mContentResolver: ContentResolver? = context.contentResolver<br><br><br>    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">callFunction</span><span class="hljs-params">(methodName: <span class="hljs-type">String</span>, bundle: <span class="hljs-type">Bundle</span>)</span></span>: Bundle? &#123;<br>        <span class="hljs-keyword">val</span> client = getClient() ?: <span class="hljs-keyword">return</span> Bundle().apply &#123;<br>            Log.e(TAG, <span class="hljs-string">&quot;callFunction <span class="hljs-variable">$methodName</span>: client is null&quot;</span>)<br>        &#125;<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">try</span> &#123;<br>            client.call(CALL_FUNCTION, methodName, bundle)<br>        &#125; <span class="hljs-keyword">catch</span> (e: Exception) &#123;<br>            Bundle()<br>        &#125; <span class="hljs-keyword">finally</span> &#123;<br>            <span class="hljs-comment">//如果频繁调用，可独立成一个函数，避免每次都close</span><br>            client.release()<br>        &#125;<br>    &#125;<br><br>    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">setParams</span><span class="hljs-params">(</span></span><br><span class="hljs-params"><span class="hljs-function">        obj: <span class="hljs-type">Any</span>? = <span class="hljs-literal">null</span>,</span></span><br><span class="hljs-params"><span class="hljs-function">        obj2: <span class="hljs-type">Any</span>? = <span class="hljs-literal">null</span>,</span></span><br><span class="hljs-params"><span class="hljs-function">        obj3: <span class="hljs-type">Any</span>? = <span class="hljs-literal">null</span>,</span></span><br><span class="hljs-params"><span class="hljs-function">        obj4: <span class="hljs-type">Any</span>? = <span class="hljs-literal">null</span>,</span></span><br><span class="hljs-params"><span class="hljs-function">        obj5: <span class="hljs-type">Any</span>? = <span class="hljs-literal">null</span></span></span><br><span class="hljs-params"><span class="hljs-function">    )</span></span>: Bundle &#123;<br>        <span class="hljs-keyword">val</span> bundle = Bundle()<br>        putValue(bundle, KEY_ONE, obj)<br>        putValue(bundle, KEY_TWO, obj2)<br>        putValue(bundle, KEY_THREE, obj3)<br>        putValue(bundle, KEY_FOUR, obj4)<br>        putValue(bundle, KEY_FIVE, obj5)<br>        <span class="hljs-keyword">return</span> bundle<br>    &#125;<br><br>    <span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">putValue</span><span class="hljs-params">(bundle: <span class="hljs-type">Bundle</span>, key: <span class="hljs-type">String</span>, obj: <span class="hljs-type">Any</span>?)</span></span> &#123;<br>        <span class="hljs-keyword">if</span> (obj == <span class="hljs-literal">null</span>) &#123;<br>            <span class="hljs-keyword">return</span><br>        &#125;<br>        bundle.putValue(key, obj)<br>    &#125;<br><br>    <span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getClient</span><span class="hljs-params">()</span></span>: ContentProviderClient? &#123;<br>        <span class="hljs-keyword">val</span> contentResolver = <span class="hljs-keyword">this</span>.mContentResolver ?: <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span><br>        <span class="hljs-keyword">return</span> contentResolver.acquireUnstableContentProviderClient(Uri.parse(<span class="hljs-keyword">this</span>.uriPath))<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><p>客户端</p><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs kotlin"><span class="hljs-keyword">class</span> <span class="hljs-title class_">TestProviderRPC</span>(<span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> context: Context) &#123;<br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> providerHelper =<br>        ProviderHelper(context, <span class="hljs-string">&quot;content://<span class="hljs-subst">$&#123;context.packageName&#125;</span>.rpc.provider&quot;</span>)<br><br>    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">sayHello</span><span class="hljs-params">(str: <span class="hljs-type">String</span>)</span></span> &#123;<br>        providerHelper.callFunction(MethodDef.SAY_HELLO, providerHelper.setParams(str))<br>    &#125;<br><br>    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getName</span><span class="hljs-params">()</span></span>: String &#123;<br>        <span class="hljs-keyword">val</span> ret = providerHelper.callFunction(MethodDef.GET_NAME, providerHelper.setParams())<br>        <span class="hljs-keyword">return</span> ret?.getString(ProviderHelper.KEY_RET) ?: <span class="hljs-string">&quot;&quot;</span><br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;基于Binder的4种RPC调用一般有AIDL、Messenger、借助 intent 传递 messenger 和 基于 contentprovider 的 call&lt;/p&gt;
&lt;p&gt;AIDL 和Messenger 比较常见了，可以参考：&lt;a</summary>
        
      
    
    
    
    <category term="Android IPC" scheme="https://iwesley.top/categories/Android-IPC/"/>
    
    
    <category term="android ipc" scheme="https://iwesley.top/tags/android-ipc/"/>
    
    <category term="android rpc" scheme="https://iwesley.top/tags/android-rpc/"/>
    
  </entry>
  
  <entry>
    <title>工作失败者反向操作指南</title>
    <link href="https://iwesley.top/article/589aa3ed/"/>
    <id>https://iwesley.top/article/589aa3ed/</id>
    <published>2025-10-03T13:49:34.000Z</published>
    <updated>2025-10-05T15:05:47.000Z</updated>
    
    <content type="html"><![CDATA[<p>虽然今年是我工作的第五个年头，但是我是从 2023 年下半年上了褚老师的课之后才明白职场也是有很多知识需要学习的，不能只用学生时代那套为人处事的逻辑来应对工作上的情况，需要填充职场知识库，掌握更多的工作应对策略。比如这些坑该怎么避免：有人喜欢把一个方案写的完成度很高才发出来给领导看，有人喜欢把自己掌握的知识藏起来不和别人分享，有人像个哑巴一样同事找他沟通也爱搭不理，有人喜欢把自己感受等同于对方的动机感到不爽时就跟别人对着干等等。</p><p>人进步的障碍是因为不知道自己姿势难堪，希望下面的分享对大家解决工作上面的问题有帮助，参考自向上移动课堂老师的分享。</p><h2 id="职场七大踩坑侠"><a href="#职场七大踩坑侠" class="headerlink" title="职场七大踩坑侠"></a>职场七大踩坑侠</h2><p>在职场这个生态系统中，我们常常在不经意间，扮演着一些阻碍自己成长、影响团队协作的“侠客”角色。这些角色并非出于恶意，却往往导致我们陷入“明明很努力，却总是不见效”的困境。</p><h3 id="一、害羞侠：从默默无闻的“隐形人”，到主动链接的“贡献者”"><a href="#一、害羞侠：从默默无闻的“隐形人”，到主动链接的“贡献者”" class="headerlink" title="一、害羞侠：从默默无闻的“隐形人”，到主动链接的“贡献者”"></a>一、害羞侠：从默默无闻的“隐形人”，到主动链接的“贡献者”</h3><ul><li><strong>踩坑表现</strong>：作为职场中的i人，因内向或社恐而沉默被动。会议上很少发言，回避团队社交，遇到困难不敢求助，习惯埋头干活，不主动与同事沟通等等。</li><li><strong>负面影响</strong>：你的才华和努力不为人知，个人进步缓慢，甚至可能因沟通不畅影响项目进度和职业前途。</li><li><strong>升级心法：主动破冰，逐渐对害羞脱敏，让价值被看见。</strong><ol><li><strong>调整心态</strong>：认识到职场的核心是协作创造价值。你的发言和求助，不是“麻烦别人”，而是为了共同的目标。降低心理负担，没人会时刻盯着你的“小失误”。</li><li><strong>刻意练习</strong>：从低风险沟通开始，比如会议前准备好一个问题，或附议同事的观点。</li><li><strong>结构化表达</strong>：发言前想好“第一、第二、第三”，建立自信。</li><li><strong>建立关系</strong>：主动与同事沟通，形成良好的合作关系。</li></ol></li></ul><h3 id="二、句号侠：从沟通的“终结者”，到服务的“金牌秘书”"><a href="#二、句号侠：从沟通的“终结者”，到服务的“金牌秘书”" class="headerlink" title="二、句号侠：从沟通的“终结者”，到服务的“金牌秘书”"></a>二、句号侠：从沟通的“终结者”，到服务的“金牌秘书”</h3><ul><li><strong>踩坑表现</strong>：用“好的”、“收到”、“嗯”终结对话，只回答字面问题，从不多想一步。</li><li><strong>负面影响</strong>：让对方感觉被敷衍，沟通效率低下，协作关系紧张。无形中关上了创造额外价值的大门。</li><li><strong>升级心法：植入金牌秘书心态，永远比对方多想一步。</strong><ol><li><strong>理解需求</strong>：不要答完就算，思考对方“为什么”问这个问题？他的真实需求和最终目标是什么？</li><li><strong>提供方案</strong>：沟通的目的不是“回复”，而是推动事情解决。</li><li><strong>服务意识</strong>：无论是对老板还是同事，都应抱持服务心态。你的回复应该是一颗“定心丸”，让对方感到安心和被支持。</li></ol></li></ul><h3 id="三、捡芝麻侠：从细节的“迷航员”，到聚焦重点的“领航员”"><a href="#三、捡芝麻侠：从细节的“迷航员”，到聚焦重点的“领航员”" class="headerlink" title="三、捡芝麻侠：从细节的“迷航员”，到聚焦重点的“领航员”"></a>三、捡芝麻侠：从细节的“迷航员”，到聚焦重点的“领航员”</h3><ul><li><strong>踩坑表现</strong>：抓不住重点，关注点总在无关紧要的细节或说话的“人”身上，而非“事”的核心。就像在医院碰到同学，关注点却是“好巧”，而不是“你哪里不舒服？”。</li><li><strong>负面影响</strong>：浪费自己和他人的时间，决策失焦，错过真正重要的信息，捡了芝麻丢了西瓜。</li><li><strong>升级心法：永远先问自己，“这件事的重点是什么？”</strong><ol><li><strong>目标导向</strong>：在任何沟通和任务中，先明确最终目标。所有细节都应服务于这个核心目标。</li><li><strong>信息过滤</strong>：学会过滤冗余信息，主动提问以获取关键信息，将对话引向核心议题。</li><li><strong>对事不对人</strong>：将注意力从“谁说的”转移到“说的是什么”、“事情的关键在哪里”，保持客观和专注。</li></ol></li></ul><h3 id="四、划线侠：从被动的“传声筒”，到主动的“方案设计师”"><a href="#四、划线侠：从被动的“传声筒”，到主动的“方案设计师”" class="headerlink" title="四、划线侠：从被动的“传声筒”，到主动的“方案设计师”"></a>四、划线侠：从被动的“传声筒”，到主动的“方案设计师”</h3><ul><li><strong>踩坑表现</strong>：遇到问题，直接抛给上级，成为一个只传递问题、不提供解决方案的“传声筒”。</li><li><strong>负面影响</strong>：暴露了你的懒于思考和担当不足，让领导觉得你无法独当一面。你永远在做“填空题”，而不是更有价值的“选择题”。</li><li><strong>升级心法：带着解决方案去敲门，做领导的“诸葛亮”。</strong><ol><li><strong>提供选项</strong>：准备上、中、下三策。清晰地列出方案1、2、3，并分析其利弊，供领导决策。</li><li><strong>充分思考</strong>：在提报前，通过提问和信息挖掘，尽可能完善你的方案。</li><li><strong>寻求共识</strong>：汇报后，主动询问：“你看是否有更好的方案？或者还有我没考虑到的点？”，共同寻找最佳解。</li></ol></li></ul><h3 id="五、缩脖侠：从错误的“逃避者”，到团队进步的“扫雷兵”"><a href="#五、缩脖侠：从错误的“逃避者”，到团队进步的“扫雷兵”" class="headerlink" title="五、缩脖侠：从错误的“逃避者”，到团队进步的“扫雷兵”"></a>五、缩脖侠：从错误的“逃避者”，到团队进步的“扫雷兵”</h3><ul><li><strong>踩坑表现</strong>：问题出现时，第一反应是沉默、逃避责任，甚至发现团队的“地雷”也不作声，生怕引火上身。</li><li><strong>负面影响</strong>：小问题拖成大窟窿，团队无法从错误中学习，你也会失去信任和成长的机会。</li><li><strong>升级心法：不沉默，诚恳认错，共同改进。</strong><ol><li><strong>拥抱错误</strong>：将问题视为改进的机会，坦然面对，思考“下次如何改进”。</li><li><strong>向内归因</strong>：多因一果，先从自己的环节找问题，思考如何改进流程，避免重蹈覆辙。</li><li><strong>做“扫雷侠”</strong>：发现问题，及时预警。这才是对团队和项目最大的负责。</li></ol></li></ul><h3 id="六、甩锅侠：从面子的“守护者”，到成长的“践行者”"><a href="#六、甩锅侠：从面子的“守护者”，到成长的“践行者”" class="headerlink" title="六、甩锅侠：从面子的“守护者”，到成长的“践行者”"></a>六、甩锅侠：从面子的“守护者”，到成长的“践行者”</h3><ul><li><strong>踩坑表现</strong>：出现问题不主动承担，还指责他人，将精力用于保护自己的面子。</li><li><strong>负面影响</strong>：破坏团队信任，暴露自己的不自信和能力不足。最终，会失去其他同事的支持。</li><li><strong>升级心法：敢于承认错误和承担责任，是自信的体现。</strong><ol><li><strong>自信的体现</strong>：敢于承认错误和承担责任反而是有能力自信的表现，吸取教训，下一次争取做的更好。</li><li><strong>成长为先</strong>：将精力从“保护面子”转移到“关注成长”。思考我能从这次失败中学到什么？</li><li><strong>持续精进</strong>：每天进步一点点，量变终将引发质变。你的成长，是你最坚实的“面子”。</li></ol></li></ul><h3 id="七、惊喜侠：从闭门的“独行侠”，到透明迭代的“共创家”"><a href="#七、惊喜侠：从闭门的“独行侠”，到透明迭代的“共创家”" class="headerlink" title="七、惊喜侠：从闭门的“独行侠”，到透明迭代的“共创家”"></a>七、惊喜侠：从闭门的“独行侠”，到透明迭代的“共创家”</h3><ul><li><strong>踩坑表现</strong>：接到任务后，喜欢一个人憋大招，不沟通、不汇报，直到最后一刻才拿出成果，给老板一个巨大的“惊喜”，但通常是“惊吓”。</li><li><strong>负面影响</strong>：方向一旦错误，所有努力付诸东流，浪费巨大成本。缺乏过程反馈，无法及时修正。</li><li><strong>升级心法：速出第一稿，小步快跑，持续反馈。</strong><ol><li><strong>公开透明</strong>：工作不是考试，不要藏着掖着。主动分享你的进度、思路和遇到的问题。</li><li><strong>及时汇报</strong>：建立固定的汇报节点，让老板和同事了解你的进展，这是最有效的风险管理。</li><li><strong>拥抱初版</strong>：快速拿出第一版初稿，目的不是展示完美，而是为了修正需求，逼近正确的方向。</li><li><strong>迭代思维</strong>：工作是一个不断反馈、不断改进的循环。你的价值不仅在于最终结果，更在于过程中展现的专业和透明。</li></ol></li></ul><p>最后总结就是：</p><ul><li>害羞侠：我到底要不要向上改变自己？</li><li>句号侠：对方提问的背后要解决什么问题？</li><li>捡芝麻侠：对方目前最关注什么？</li><li>划线侠：我怎么把解题往前推一步？</li><li>缩脖侠：我怎么帮团队解题扫雷？</li><li>甩锅侠：甭管谁的错，怎么做下次才能更好？</li><li>惊喜侠：怎么多快好省解决对方的问题？</li></ul><p>告别“踩坑侠”的身份，本质上是一场思维模式的革命。它要求我们从一个被动的任务执行者，转变为一个主动的价值创造者；从一个孤立的个体，转变为一个高效的协作者。逐渐从一个刚入职场的任务完成员转变成一个解题伙伴，然后成长为解题者，慢慢变成开拓者，最后成为面壁者。</p><p>赢家等于改变一个又一个 losers 的常见小错误，希望这份指南能成为你职场道路上的镜子和地图，助你时时自省，步步为赢，向上移动。</p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;虽然今年是我工作的第五个年头，但是我是从 2023</summary>
        
      
    
    
    
    <category term="随笔" scheme="https://iwesley.top/categories/%E9%9A%8F%E7%AC%94/"/>
    
    
    <category term="随笔" scheme="https://iwesley.top/tags/%E9%9A%8F%E7%AC%94/"/>
    
  </entry>
  
  <entry>
    <title>年轻的时候友情是一种像爱情那样燃烧的东西</title>
    <link href="https://iwesley.top/article/36e38a03/"/>
    <id>https://iwesley.top/article/36e38a03/</id>
    <published>2025-09-27T13:20:31.000Z</published>
    <updated>2026-08-08T12:59:35.788Z</updated>
    
    <content type="html"><![CDATA[<h2 id="1"><a href="#1" class="headerlink" title="1"></a>1</h2><p>海明威说过：“人生最大的遗憾，是一个人无法同时拥有青春和对青春的感受。”</p><p>在毕业五年后的今天，我更加深刻地理解了这一句话。它像一个开关，轻轻一按，便打开了记忆的闸门：是关于友情的。</p><p>我以往很少去看过去的东西，比如拍过的照片、自己或者别人的朋友圈、空间等等。这可能是因为人年轻时，周边都是同学朋友，没有过多的忧虑，都在憧憬未来，正处于一个上升阶段，理所当然地向前冲，容易自我和忽略身边人的感受等等。这样阶段的人，一般来说很难怀念过去，或者说当下就是未来的回忆，现在不需要怀念。当人成长到一定年龄后，有了更多的生活经验，有了更多的酸甜苦辣体验，生活平常、不忙甚至不如意时，才会有审视现在和过去的间隙，有可能怀念过去，特别是美好的过去。</p><h2 id="2"><a href="#2" class="headerlink" title="2"></a>2</h2><p>最近，我一头扎进那些尘封的角落，发现了许多美好的、温暖的、甚至曾被疏忽的过往。没想到，那些当初被忽略的细节，反倒成了回忆里最清晰的注脚。虽然好多曾经无话不谈的朋友，如今已经渐行渐远，静静地躺在彼此的联系人列表里，生活的洪流将我们推向了不同的方向和未来，但是当我翻看那些过去的照片，聊天短信、记录，回首共同的经历，重读那些充满青春气息又真诚的留言时，那段旅程的温暖便会立刻将我包围。我知道，那份温暖会永远珍藏在我心里。</p><p>比如在 QQ 空间我发现了一些从来没有见过的记录或者早已尘封的往事：LYW、ZYY同学那里，我发现，原来他们曾经也和自己一样，喜欢在自己的留言区自言自语，记录下那些不为人知的心事和对生活的感慨，甚至还有 cue 我的留言。在那一刻，感觉到复杂情感的同时，也仿佛看到了另一个自己，一种跨越时空的奇妙共鸣油然而生；CJY同学那里，我看到了感谢初三我帮她耐心解题的感谢和祝福的说说，还有一张我从来未见过的关于我在教室座位的图片，突然感动。留言区和评论区那里，原来我和TA也曾经这样无话不谈，原来TA也曾经这样关心我，原来我曾经这样地忽略了TA 的感受，百感交集。曾经的我们，在空间写下了好多青春感悟，发表了好多照片，虽然一部分现在看起来有点幼稚，但这也是青春动人的地方啊，愿意分享，袒露心声，没有城府，没有过多的顾虑，肆意抒发情感，互相热切交流，太美好了。当然，好多人的空间或者朋友圈都三天可见了，或者删除了，略感遗憾。</p><p>还有很多和好朋友同学一起的经历：</p><p>小学同学、邻居：小学六年都没有分过班，遇上了几位好朋友，我们一起打羽毛球，骑自行车去玩，去同学家里烤番薯等等。有一次我们骑车去爬山，有一位小伙伴要我们把他埋在土里，最后只露出个头，他想挣脱，但根本不可能。最后还是要我们把土刨开，他才能重新站起来。他叫THJ，还借了我好多书，一起和我打类似小霸王那样的游戏机，打扑克牌等等，真的无忧无虑。邻居也相处了六年，那时候没有手机，我们一起玩捉迷藏，一起玩游戏，抓知了，玩炮仗，还不知好歹，把炸药重新倒出重新压制成更大的炮仗，不知道压力会导致爆炸的危险。有一次，我用玩具枪打中了QSY，弄哭了她，我当时突然就把枪砸在地上，再也没有玩过了。有时候，我们还聊天到深夜，跑到漆黑的马路上面去探险，回想起来也挺刺激的。后来，我去了县城一中，再也没有见过他们。</p><p>继续说说LYW 同学，我和他到现在还是很好的朋友。还记得我们高三那段时期，有时候早上 6 点前就起来去操场跑步，晚上的时候去后山跑，对于处于高三压力生活下的我们，运动出汗的感觉真好，任何烦恼在这过程中都突然消失了。我和他唯一一次激烈冲突是在高三的时候，我给他买了一个快递，好像是牛奶，我叫他去拿，实际上我帮他拿回去了，然后他就白跑一趟，找不到快递，回来宿舍的时候觉得我耍了他，很生气，冲我大喊大叫。因为这个我们好几天没有说话。某个时刻，我们相视而笑，和好如初。初到他广州的家中做客，离别时，他妈妈硬塞给我一个大红包，攥在手里，感觉暖暖的。他也是“好好的”6 人群组的 connector：曾经一起去溜冰，去外面吃饭，去L家烧烤，为苦闷的高三读书生活增添了不少乐趣。毕业多年，许多人都走散了，而我们还能每年一聚，这份坚持，弥足珍贵。</p><p>HZF 和 LWZ，我的初中同学。人生中的许多第一次都是和他们一起经历的：第一次吃肯德基、第一次唱K、第一次看电影，第一次看大海等等。初二的时候家里还没有宽带，LWZ同学帮我下载的 Beyond、张国荣等的演唱会，仍然存在我的硬盘里。</p><p>Ling，一位活泼可爱的朋友。高一上学期坐在我前面，但下学期我们在不同班了。我没想到后面和她还有好多交集。因为她有一个好朋友 JL 跟我在同一个班，来找她时经常跟我打招呼，会拍一下我的肩膀，觉得挺有趣的。后来在 QQ 慢慢交流多了，就成了好朋友。虽然我们在网上聊得很开心，但可能出于性格原因，有一次体育文化艺术节，我在教室长廊碰到她时，所有的熟悉都突然消失了，竟然很木讷地打了招呼就走了，留下一个笨拙的背影。后来我们还分享过读书心得，生活和学习体验，但有一点遗憾的是我跟她从来没合过影，拍毕业照那天没有看到她，唯一的合影应该就是在表彰栏上面了。后来高考完后，如果没有记忆错误，JL 同学还说过要一起去海南玩。但后来因为高考不如意，这个计划落空。我和她们最后的线下聚会貌似都停在了 2017，后来过年在超市碰到过Ling，但只有寒暄。再后来，基本就是线上的偶尔交流了。时光流转，多年以后，我们竟又生活在了同一座城市。命运仿佛开了一个温柔的玩笑，将我们重新安置在彼此附近的人海里，近在咫尺，又远在天涯。</p><p>CJJ，高一高二同学，有点腼腆，爱笑，熟了之后很聊得来。2015 年高二学期结束时手写了一封信给我，除了感谢我一些学习上的帮助外，还祝我 18 岁生日快乐。虽然高三不在同一个班，但我偶尔会在晚自习前去找她，聊学习，也聊点别的。她家离我家很近，17 还是 18 年春节的时候，我去她家吃过年例。毕业后各忙各的，见面的机会越来越少了。 2020 年国庆节去广州玩时找过她一次，逛公园，走了好久的路。</p><p>Dong，初二同学，高一同桌，和我一样是手机疯狂爱好者，都喜欢小米，经常折腾手机、刷机，喜欢篮球，看电脑报。有一次用红米的时候，在支付时手机系统无响应，尴尬不已，他就再也没有用过安卓手机，转向苹果了。在他的数码相机里，留下了好多校内活动和生活照片，充满了回忆。我们一起设计的校徽拿过奖，在班级上合唱过《光辉岁月》，但那个唱歌场面的视频我现在还不敢回看，我记得我很紧张，脚控制不住地在抖，感觉挺出丑的。他毕业后也来了深圳，后来去了香港读研，现在在上海。</p><p>FZC。高一上学期认识，下学期分班时，我主动问他可不可以做同桌，他欣然接受，一起并肩作战了一年多。上学期间还跑到他家吃年例。大一见过一次，大学毕业后聚了一次。</p><p>LHR。从肇庆开车跑到深圳载我一起回粤西，搞到凌晨两三点才回到家，吃了一顿牛腩粉，够意思！</p><p>Deng。认识很久了，我跟她有共同的亲戚，初一的同桌，初二、整个高中基本都在同一班。但初一时虽然我们是同桌，但貌似没怎么说过话，因为那时候我真的不知道怎么跟女同学聊天，太拘谨，太失败了。后来，我们在英语夏令营同一个班度过了一个美好的暑假，也是那时候发现一群年轻人跳舞是真的很 high。</p><p>PHJ。一起打乒乓球，一起到校外面加餐。</p><p>WJX。初一同学，但那时候不熟，我好像记得他写了一个投诉纸条给老师，说教室鬼哭狼嚎，过于夸张，其实就是吵闹。高二成为了好朋友，搞学习小组，图书角，一起探讨学习。记得有一次，我认为物理老师说的题有问题，我不敢去说叫他去问，结果最后老师还是固执己见，不肯探讨，他灰溜溜地回来了。高三前夕带我去广州，住在他姐家里。那是我人生第二次去广州，小时候去过一次，但基本没有记忆了。去逛了大学、图书馆、博物馆，也是一段很美好的回忆了。</p><p>Q学姐，心地善良，我咨询她关于大学的疑惑时乐于解答，还愿意主动把一卡通账号借给我抢课，因为高年级的学生有优先选择权，最后在夜深人静的时候偷偷释放，自己再选入。当然，我这种行为是不好的，建议不要学习。</p><p>大学室友，Z，W，C。我们一起去乌镇，去上海，看电影，唱K，吃吃吃。Z 是最喜欢玩的，能带动我们，他自己也去各个地方吃喝玩乐。我很遗憾那时候没有意识跟他多出去外面走走，现在心境完全不同了。</p><p>高考后，我去了杭州读书，很多好朋友都留在了广东。一般来说，一个异乡人在外面漂泊，肯定会感到孤独的，可能人这一辈子，从来没有像那些年一样，如此需要同龄人的陪伴，如此需要友谊，如此需要诉说。</p><p>感谢 Su 和 Ma 的陪伴，感谢我们三的Send You A Bullet群组。如果没有记错，我们大学四年群里每天都有说话聊天，比如今天碰到什么有趣的事情啊，选课啊，吐槽啊，话题无所顾忌，热切回应。我们一起开黑，一起吃鸡，一起合种树，一起去深圳、香港，是我人生里很快乐的一段时期。直到今天，我们仍然愉快相处，但话密度肯定不能回到从前了，因为人不可能永远停留在过去，会有工作，新的生活、责任和陪伴，我们不可能再像年轻时那样潇洒，那样在“中央公园咖啡馆”说个不停，那样无忧无虑。</p><h2 id="3"><a href="#3" class="headerlink" title="3"></a>3</h2><p>6 月份的时候，我终于完整地看完了《老友记》，这是从大学就开始看的情景剧，持续了七八年。现在看的感受和之前看的完全不一样了，从剧中人成为了旁观者，不再年轻，也更能体会他们在一起的快乐，更能体会那段时期的美好和珍贵。当你反反复复看一部剧时，你和他们就成为了好朋友、亲人。</p><p>几段书摘：</p><p>押沙龙老师：</p><blockquote><p>《老友记》的迷人之处在于它的青春自由气息，里面的六个人物都过了青春期，但又没有成家立业(罗斯有孩子但也很虚化)。这个时期，他们成熟又没有太成熟，社会化又没有完全社会化，处于生命中最自由的一段日子。所以，他们身上才会有那样的光彩，显示出近乎无限的可能。<br>那个时期的友谊是如此的重要，如此的炫目，足以支撑起生活的全部。但是以后他们终究会渐渐走失。没有永远影形不离的朋友，昔日热烈的友情会慢慢褪色为温情，就像火中之木会渐渐烧为木炭一样，温暖，但不再热烈。回过头来看，那就像人生中的一段童话时期。《老友记》就像这样一部人生的童话，让人看了以后就会心生欢喜，想起自由，想起光亮，想起那些终将消逝的美好。</p></blockquote><p>读《一个人的村庄》的评论：</p><blockquote><p>2024&#x2F;10&#x2F;17</p><p>记忆是容易模糊的，但更多时候是被埋藏起来了，唤醒它们的方法最容易的应该是“触景生情”，比如回到过去的地方，比如翻阅书信、照片等。今年国庆节回家的时候，猛然发现之前的一些书信丢失了，感到非常惋惜。后来意识到一切纸质的东西都有可能丢失，所以这次回来顺便将以前的证书、照片等都进行扫描并数字化保存了。 很多人可能没意识到，过去拍的照片可能都可以组成一部电影或者电视剧了，放映的是我们过去酸甜苦辣的人生。所以，尽情记录吧。</p><p>2024&#x2F;10&#x2F;4</p><p>这次国庆回家翻看了以前的照片，想起了很多事情，猛然发觉以前因为走的太快或者说是太顺错过了不少东西。或许这就是人性的弱点，高歌猛进或者日夜为生计奔波等就容易忽略周边的人或者物，唏嘘。🙁</p></blockquote><p>我一直都在：《老友记》幕后的故事</p><blockquote><p>有些事情只属于过去，《老友记》是属于过去的时光。在这个浩渺的宇宙里，它讲述了亲密关系、爱和成长。《老友记》一直在我们的共同回忆里，与这份回忆共存的还有旧室友、初恋情人，朋友间才懂的笑话，在车里调高音量、降低车窗大声唱的俗气歌曲。在回顾过去的时候，我们既甜蜜又悲伤——看着老照片发笑，看着发型又哭又笑。但是，正如勒布朗所说的那样：我们回不到过去，回不到那些人、那些地方。他们变了，我们也变了，这就是人生。最好把他们留在那里。这样，我们永远不会丢掉这些记忆。我们会永远知道他们在哪里。</p></blockquote><p>毛姆《人性的枷锁》：</p><blockquote><p>“He thought of Hayward and his eager admiration for him when first they met, and how disillusion had come and then indifference, till nothing held them together but habit and old memories. It was one of the queer things of life that you saw a person every day for months and were so intimate with him that you could not imagine existence without him; then separation came, and everything went on in the same way, and the companion who had seemed essential proved unnecessary. Your life proceeded and you did not even miss him. ”</p></blockquote><h2 id="4"><a href="#4" class="headerlink" title="4"></a>4</h2><p>年轻的时候，友情是一种像爱情那样燃烧的东西。</p><p>谢谢你们的陪伴。那是我们再也回不去的日子，一个人一辈子只能经历一次。</p><p>没有你们，青春时代会是多么的苍白无趣。<br>没有你们，那时的我会是多么的孤独无助。<br>谢谢你们，在那段日子里，出现在我的身边。</p><p>我未曾珍惜的，我不再拥有。</p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;h2 id=&quot;1&quot;&gt;&lt;a href=&quot;#1&quot; class=&quot;headerlink&quot;</summary>
        
      
    
    
    
    <category term="随笔" scheme="https://iwesley.top/categories/%E9%9A%8F%E7%AC%94/"/>
    
    
    <category term="随笔" scheme="https://iwesley.top/tags/%E9%9A%8F%E7%AC%94/"/>
    
  </entry>
  
  <entry>
    <title>安卓14系统应用收不到开机广播</title>
    <link href="https://iwesley.top/article/3afe9d6d/"/>
    <id>https://iwesley.top/article/3afe9d6d/</id>
    <published>2025-08-17T07:35:08.000Z</published>
    <updated>2025-09-09T12:33:18.000Z</updated>
    
    <content type="html"><![CDATA[<p>前段时间有测试反馈在安卓14 上面某系统应用恢复出厂设置后没有自启动，究竟是什么原因呢？</p><h2 id="回顾"><a href="#回顾" class="headerlink" title="回顾"></a>回顾</h2><p>Android 从3.1开始，会将新安装并且从未被启动的应用置为“STOPPED”状态，或者被force stop的应用，这种状态下的应用是无法接收到广播的。但发送方可以通过添加<code>FLAG_INCLUDE_STOPPED_PACKAGES</code> 来豁免，但一般情况下，系统会默认添加<code>FLAG_EXCLUDE_STOPPED_PACKAGES</code> flag。</p><p><a href="http://xrefandroid.com/android-16.0.0_r2/s?refs=FLAG_EXCLUDE_STOPPED_PACKAGES&project=frameworks">http://xrefandroid.com/android-16.0.0_r2/s?refs=FLAG_EXCLUDE_STOPPED_PACKAGES&amp;project=frameworks</a></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * If set, this intent will not match any components in packages that</span><br><span class="hljs-comment"> * are currently</span><br><span class="hljs-comment"> * &#123;<span class="hljs-doctag">@linkplain</span> android.content.pm.ApplicationInfo#FLAG_STOPPED stopped&#125;.</span><br><span class="hljs-comment"> * If this is not set, then the default behavior is to include such</span><br><span class="hljs-comment"> * applications in the result.</span><br><span class="hljs-comment"> */</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">int</span> <span class="hljs-variable">FLAG_EXCLUDE_STOPPED_PACKAGES</span> <span class="hljs-operator">=</span> <span class="hljs-number">0x00000010</span>;<br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * If set, this intent will always match any components in packages that</span><br><span class="hljs-comment"> * are currently</span><br><span class="hljs-comment"> * &#123;<span class="hljs-doctag">@linkplain</span> android.content.pm.ApplicationInfo#FLAG_STOPPED stopped&#125;.</span><br><span class="hljs-comment"> * This is the default behavior when</span><br><span class="hljs-comment"> * &#123;<span class="hljs-doctag">@link</span> #FLAG_EXCLUDE_STOPPED_PACKAGES&#125; is not set.  If both of these</span><br><span class="hljs-comment"> * flags are set, this one wins (it allows overriding of exclude for</span><br><span class="hljs-comment"> * places where the framework may automatically set the exclude flag,</span><br><span class="hljs-comment"> * such as broadcasts).</span><br><span class="hljs-comment"> */</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">int</span> <span class="hljs-variable">FLAG_INCLUDE_STOPPED_PACKAGES</span> <span class="hljs-operator">=</span> <span class="hljs-number">0x00000020</span>;<br><br></code></pre></td></tr></table></figure><h3 id="豁免"><a href="#豁免" class="headerlink" title="豁免"></a>豁免</h3><p><a href="http://xrefandroid.com/android-13.0.0_r83/xref/frameworks/base/services/core/java/com/android/server/IntentResolver.java#808">IntentResolver.java - OpenGrok cross reference for &#x2F;frameworks&#x2F;base&#x2F;services&#x2F;core&#x2F;java&#x2F;com&#x2F;android&#x2F;server&#x2F;IntentResolver.java</a></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">buildResolveList</span><span class="hljs-params">(<span class="hljs-meta">@NonNull</span> Computer computer, Intent intent,</span><br><span class="hljs-params">            FastImmutableArraySet&lt;String&gt; categories, <span class="hljs-type">boolean</span> debug, <span class="hljs-type">boolean</span> defaultOnly,</span><br><span class="hljs-params">            String resolvedType, String scheme, F[] src, List&lt;R&gt; dest, <span class="hljs-type">int</span> userId,</span><br><span class="hljs-params">            <span class="hljs-type">long</span> customFlags)</span> &#123; <br>           ...........<br>           <span class="hljs-keyword">if</span> (excludingStopped &amp;&amp; isFilterStopped(computer.getPackageStateInternal(packageName),<br>                    userId)) &#123;<br>                <span class="hljs-keyword">if</span> (debug) &#123;<br>                    Slog.v(TAG, <span class="hljs-string">&quot;  Filter&#x27;s target is stopped; skipping&quot;</span>);<br>                &#125;<br>                <span class="hljs-keyword">continue</span>;<br>            &#125;<br>          ..................<br>&#125;<br></code></pre></td></tr></table></figure><p><a href="http://xrefandroid.com/android-13.0.0_r83/xref/frameworks/base/services/core/java/com/android/server/pm/resolution/ComponentResolver.java">ComponentResolver.java - OpenGrok cross reference for &#x2F;frameworks&#x2F;base&#x2F;services&#x2F;core&#x2F;java&#x2F;com&#x2F;android&#x2F;server&#x2F;pm&#x2F;resolution&#x2F;ComponentResolver.java</a></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Override</span><br><span class="hljs-keyword">protected</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">isFilterStopped</span><span class="hljs-params">(<span class="hljs-meta">@Nullable</span> PackageStateInternal packageState,</span><br><span class="hljs-params">        <span class="hljs-meta">@UserIdInt</span> <span class="hljs-type">int</span> userId)</span> &#123;<br>    <span class="hljs-keyword">if</span> (!mUserManager.exists(userId)) &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br>    &#125;<br><br>    <span class="hljs-keyword">if</span> (packageState == <span class="hljs-literal">null</span> || packageState.getPkg() == <span class="hljs-literal">null</span>) &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br>    &#125;<br><br>    <span class="hljs-comment">// System apps are never considered stopped for purposes of</span><br>    <span class="hljs-comment">// filtering, because there may be no way for the user to</span><br>    <span class="hljs-comment">// actually re-launch them.</span><br>    <span class="hljs-keyword">return</span> !packageState.isSystem()<br>            &amp;&amp; packageState.getUserStateOrDefault(userId).isStopped();<br>&#125;<br></code></pre></td></tr></table></figure><p>安卓 14 之前的代码表明系统应用（系统标记为<code>ApplicationInfo.FLAG_SYSTEM</code> 的应用）是可以豁免的。</p><blockquote><p>注意： 直接安装在 data 分区的 system uid 应用是不会被标记为ApplicationInfo.FLAG_SYSTEM 的。但更新在 data 分区的系统应用依然有效。</p></blockquote><h2 id="安卓-14-的变化"><a href="#安卓-14-的变化" class="headerlink" title="安卓 14 的变化"></a>安卓 14 的变化</h2><p><a href="http://xrefandroid.com/android-14.0.0_r21/xref/frameworks/base/services/core/java/com/android/server/pm/resolution/ComponentResolver.java">ComponentResolver.java - OpenGrok cross reference for &#x2F;frameworks&#x2F;base&#x2F;services&#x2F;core&#x2F;java&#x2F;com&#x2F;android&#x2F;server&#x2F;pm&#x2F;resolution&#x2F;ComponentResolver.java</a></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Override</span><br><span class="hljs-keyword">protected</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">isFilterStopped</span><span class="hljs-params">(<span class="hljs-meta">@NonNull</span> Computer computer, F filter,</span><br><span class="hljs-params">        <span class="hljs-meta">@UserIdInt</span> <span class="hljs-type">int</span> userId)</span> &#123;<br>    <span class="hljs-keyword">if</span> (!mUserManager.exists(userId)) &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br>    &#125;<br><br>    <span class="hljs-keyword">final</span> <span class="hljs-type">PackageStateInternal</span> <span class="hljs-variable">packageState</span> <span class="hljs-operator">=</span> computer.getPackageStateInternal(<br>            filter.first.getPackageName());<br>    <span class="hljs-keyword">if</span> (packageState == <span class="hljs-literal">null</span> || packageState.getPkg() == <span class="hljs-literal">null</span>) &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br>    &#125;<br><br>    <span class="hljs-keyword">return</span> packageState.getUserStateOrDefault(userId).isStopped();<br>&#125;<br></code></pre></td></tr></table></figure><p><del>系统应用不能豁免了，一刀切了。🤣 当然，这里可以打补丁让原来的修改有效。</del></p><h3 id="PS（2025-年-9-月-9-日更新）"><a href="#PS（2025-年-9-月-9-日更新）" class="headerlink" title="PS（2025 年 9 月 9 日更新）"></a>PS（2025 年 9 月 9 日更新）</h3><p>和安卓 15 一样可以通过<a href="http://xrefandroid.com/android-14.0.0_r21/xref/frameworks/base/data/etc/initial-package-stopped-states.xml">initial-package-stopped-states.xml - OpenGrok cross reference for &#x2F;frameworks&#x2F;base&#x2F;data&#x2F;etc&#x2F;initial-package-stopped-states.xml</a>配置豁免。</p><p><a href="http://xrefandroid.com/android-14.0.0_r21/s?refs=scanSystemPackageLI&project=frameworks">http://xrefandroid.com/android-14.0.0_r21/s?refs=scanSystemPackageLI&amp;project=frameworks</a></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// A new application appeared on /system, and we are seeing it for the first time.</span><br><span class="hljs-comment">// Its also not updated as we don&#x27;t have a copy of it on /data. So, scan it in a</span><br><span class="hljs-comment">// STOPPED state.</span><br><span class="hljs-comment">// We&#x27;ll skip this step under the following conditions:</span><br><span class="hljs-comment">//   - It&#x27;s &quot;android&quot;</span><br><span class="hljs-comment">//   - It&#x27;s an APEX or overlay package since stopped state does not affect them.</span><br><span class="hljs-comment">//   - It is enumerated with a &lt;initial-package-state&gt; tag having the stopped attribute</span><br><span class="hljs-comment">//     set to false</span><br><span class="hljs-comment">//   - It doesn&#x27;t have an enabled and exported launcher activity, which means the user</span><br><span class="hljs-comment">//     wouldn&#x27;t have a way to un-stop it</span><br><span class="hljs-keyword">final</span> <span class="hljs-type">boolean</span> <span class="hljs-variable">isApexPkg</span> <span class="hljs-operator">=</span> (scanFlags &amp; SCAN_AS_APEX) != <span class="hljs-number">0</span>;<br><span class="hljs-keyword">if</span> (mPm.mShouldStopSystemPackagesByDefault<br>        &amp;&amp; scanSystemPartition<br>        &amp;&amp; !pkgAlreadyExists<br>        &amp;&amp; !isApexPkg<br>        &amp;&amp; !parsedPackage.isOverlayIsStatic()<br>) &#123;<br>    <span class="hljs-type">String</span> <span class="hljs-variable">packageName</span> <span class="hljs-operator">=</span> parsedPackage.getPackageName();<br>    <span class="hljs-keyword">if</span> (!<span class="hljs-string">&quot;android&quot;</span>.contentEquals(packageName)<br>            &amp;&amp; !mPm.mInitialNonStoppedSystemPackages.contains(packageName)<br>            &amp;&amp; hasLauncherEntry(parsedPackage)) &#123;<br>        scanFlags |= SCAN_AS_STOPPED_SYSTEM_APP;<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">final</span> <span class="hljs-type">ScanResult</span> <span class="hljs-variable">scanResult</span> <span class="hljs-operator">=</span> scanPackageNewLI(parsedPackage, parseFlags,<br>        scanFlags | SCAN_UPDATE_SIGNATURE, <span class="hljs-number">0</span> <span class="hljs-comment">/* currentTime */</span>, user, <span class="hljs-literal">null</span>);<br></code></pre></td></tr></table></figure><p><a href="http://xrefandroid.com/android-14.0.0_r21/xref/frameworks/base/services/core/java/com/android/server/pm/ScanPackageUtils.java#202">ScanPackageUtils.java - OpenGrok cross reference for &#x2F;frameworks&#x2F;base&#x2F;services&#x2F;core&#x2F;java&#x2F;com&#x2F;android&#x2F;server&#x2F;pm&#x2F;ScanPackageUtils.java</a></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">if</span> (createNewPackage) &#123;<br>            <span class="hljs-keyword">final</span> <span class="hljs-type">boolean</span> <span class="hljs-variable">instantApp</span> <span class="hljs-operator">=</span> (scanFlags &amp; SCAN_AS_INSTANT_APP) != <span class="hljs-number">0</span>;<br>            <span class="hljs-keyword">final</span> <span class="hljs-type">boolean</span> <span class="hljs-variable">virtualPreload</span> <span class="hljs-operator">=</span> (scanFlags &amp; SCAN_AS_VIRTUAL_PRELOAD) != <span class="hljs-number">0</span>;<br>            <span class="hljs-keyword">final</span> <span class="hljs-type">boolean</span> <span class="hljs-variable">isStoppedSystemApp</span> <span class="hljs-operator">=</span> (scanFlags &amp; SCAN_AS_STOPPED_SYSTEM_APP) != <span class="hljs-number">0</span>;<br><br>            <span class="hljs-comment">// Flags contain system values stored in the server variant of AndroidPackage,</span><br>            <span class="hljs-comment">// and so the server-side PackageInfoUtils is still called, even without a</span><br>            <span class="hljs-comment">// PackageSetting to pass in.</span><br>            <span class="hljs-type">int</span> <span class="hljs-variable">pkgFlags</span> <span class="hljs-operator">=</span> PackageInfoUtils.appInfoFlags(parsedPackage, <span class="hljs-literal">null</span>);<br>            <span class="hljs-type">int</span> <span class="hljs-variable">pkgPrivateFlags</span> <span class="hljs-operator">=</span> PackageInfoUtils.appInfoPrivateFlags(parsedPackage, <span class="hljs-literal">null</span>);<br><br>            <span class="hljs-comment">// REMOVE SharedUserSetting from method; update in a separate call</span><br>            pkgSetting = Settings.createNewSetting(parsedPackage.getPackageName(),<br>                    originalPkgSetting, disabledPkgSetting, realPkgName, sharedUserSetting,<br>                    destCodeFile, parsedPackage.getNativeLibraryRootDir(),<br>                    AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage),<br>                    AndroidPackageUtils.getRawSecondaryCpuAbi(parsedPackage),<br>                    parsedPackage.getLongVersionCode(), pkgFlags, pkgPrivateFlags, user,<br>                    <span class="hljs-literal">true</span> <span class="hljs-comment">/*allowInstall*/</span>, instantApp, virtualPreload, isStoppedSystemApp,<br>                    UserManagerService.getInstance(), usesSdkLibraries,<br>                    parsedPackage.getUsesSdkLibrariesVersionsMajor(), usesStaticLibraries,<br>                    parsedPackage.getUsesStaticLibrariesVersions(), parsedPackage.getMimeGroups(),<br>                    newDomainSetId);<br>        &#125;<br></code></pre></td></tr></table></figure><p><a href="http://xrefandroid.com/android-14.0.0_r21/s?defs=createNewSetting&project=frameworks">http://xrefandroid.com/android-14.0.0_r21/s?defs=createNewSetting&amp;project=frameworks</a></p><p>通过isStoppedSystemApp 来控制应用是不是标记为ApplicationInfo.FLAG_STOPPED 状态，非系统应用安装时默认为ApplicationInfo.FLAG_STOPPED 状态，isStoppedSystemApp 为真时，系统应用也会被标记为ApplicationInfo.FLAG_STOPPED。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// If this is not a system app, it starts out stopped.</span><br><span class="hljs-keyword">if</span> ((pkgFlags&amp;ApplicationInfo.FLAG_SYSTEM) == <span class="hljs-number">0</span>) &#123;<br>    <span class="hljs-keyword">if</span> (DEBUG_STOPPED) &#123;<br>        <span class="hljs-type">RuntimeException</span> <span class="hljs-variable">e</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(<span class="hljs-string">&quot;here&quot;</span>);<br>        e.fillInStackTrace();<br>        Slog.i(PackageManagerService.TAG, <span class="hljs-string">&quot;Stopping package &quot;</span> + pkgName, e);<br>    &#125;<br>    List&lt;UserInfo&gt; users = getAllUsers(userManager);<br>    <span class="hljs-keyword">if</span> (users != <span class="hljs-literal">null</span> &amp;&amp; allowInstall) &#123;<br>        <span class="hljs-keyword">for</span> (UserInfo user : users) &#123;<br>            <span class="hljs-comment">// By default we consider this app to be installed</span><br>            <span class="hljs-comment">// for the user if no user has been specified (which</span><br>            <span class="hljs-comment">// means to leave it at its original value, and the</span><br>            <span class="hljs-comment">// original default value is true), or we are being</span><br>            <span class="hljs-comment">// asked to install for all users, or this is the</span><br>            <span class="hljs-comment">// user we are installing for.</span><br>            <span class="hljs-keyword">final</span> <span class="hljs-type">boolean</span> <span class="hljs-variable">installed</span> <span class="hljs-operator">=</span> installUser == <span class="hljs-literal">null</span><br>                    || (installUserId == UserHandle.USER_ALL<br>                        &amp;&amp; !isAdbInstallDisallowed(userManager, user.id)<br>                        &amp;&amp; !user.preCreated)<br>                    || installUserId == user.id;<br>            <span class="hljs-keyword">if</span> (DEBUG_MU) &#123;<br>                Slogf.d(TAG, <span class="hljs-string">&quot;createNewSetting(pkg=%s, installUserId=%s, user=%s, &quot;</span><br>                        + <span class="hljs-string">&quot;installed=%b)&quot;</span>,<br>                        pkgName, installUserId, user.toFullString(), installed);<br>            &#125;<br>            pkgSetting.setUserState(user.id, <span class="hljs-number">0</span>, COMPONENT_ENABLED_STATE_DEFAULT,<br>                    installed,<br>                    <span class="hljs-literal">true</span> <span class="hljs-comment">/*stopped*/</span>,<br>                    <span class="hljs-literal">true</span> <span class="hljs-comment">/*notLaunched*/</span>,<br>                    <span class="hljs-literal">false</span> <span class="hljs-comment">/*hidden*/</span>,<br>                    <span class="hljs-number">0</span> <span class="hljs-comment">/*distractionFlags*/</span>,<br>                    <span class="hljs-literal">null</span> <span class="hljs-comment">/*suspendParams*/</span>,<br>                    instantApp,<br>                    virtualPreload,<br>                    <span class="hljs-literal">null</span> <span class="hljs-comment">/*lastDisableAppCaller*/</span>,<br>                    <span class="hljs-literal">null</span> <span class="hljs-comment">/*enabledComponents*/</span>,<br>                    <span class="hljs-literal">null</span> <span class="hljs-comment">/*disabledComponents*/</span>,<br>                    PackageManager.INSTALL_REASON_UNKNOWN,<br>                    PackageManager.UNINSTALL_REASON_UNKNOWN,<br>                    <span class="hljs-literal">null</span> <span class="hljs-comment">/*harmfulAppWarning*/</span>,<br>                    <span class="hljs-literal">null</span> <span class="hljs-comment">/*splashscreenTheme*/</span>,<br>                    <span class="hljs-number">0</span> <span class="hljs-comment">/*firstInstallTime*/</span>,<br>                    PackageManager.USER_MIN_ASPECT_RATIO_UNSET<br>            );<br>        &#125;<br>    &#125;<br>&#125; <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (isStoppedSystemApp) &#123;<br>    <span class="hljs-keyword">if</span> (DEBUG_STOPPED) &#123;<br>        <span class="hljs-type">RuntimeException</span> <span class="hljs-variable">e</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(<span class="hljs-string">&quot;here&quot;</span>);<br>        e.fillInStackTrace();<br>        Slog.i(PackageManagerService.TAG, <span class="hljs-string">&quot;Stopping system package &quot;</span> + pkgName, e);<br>    &#125;<br>    pkgSetting.setStopped(<span class="hljs-literal">true</span>, installUserId);<br>&#125;<br></code></pre></td></tr></table></figure><h2 id="安卓-15-峰回路转"><a href="#安卓-15-峰回路转" class="headerlink" title="安卓 15 峰回路转"></a>安卓 15 峰回路转</h2><p><a href="http://xrefandroid.com/android-15.0.0_r1/xref/frameworks/base/services/core/java/com/android/server/pm/resolution/ComponentResolver.java">ComponentResolver.java - OpenGrok cross reference for &#x2F;frameworks&#x2F;base&#x2F;services&#x2F;core&#x2F;java&#x2F;com&#x2F;android&#x2F;server&#x2F;pm&#x2F;resolution&#x2F;ComponentResolver.java</a></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs java">    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">protected</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">isFilterStopped</span><span class="hljs-params">(<span class="hljs-meta">@NonNull</span> Computer computer, F filter,</span><br><span class="hljs-params">            <span class="hljs-meta">@UserIdInt</span> <span class="hljs-type">int</span> userId)</span> &#123;<br>        <span class="hljs-keyword">if</span> (!mUserManager.exists(userId)) &#123;<br>            <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br>        &#125;<br><br>        <span class="hljs-keyword">final</span> <span class="hljs-type">PackageStateInternal</span> <span class="hljs-variable">packageState</span> <span class="hljs-operator">=</span> computer.getPackageStateInternal(<br>                filter.first.getPackageName());<br>        <span class="hljs-keyword">if</span> (packageState == <span class="hljs-literal">null</span> || packageState.getPkg() == <span class="hljs-literal">null</span>) &#123;<br>            <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br>        &#125;<br><br>        <span class="hljs-keyword">if</span> (packageState.isSystem()) &#123;<br>            <span class="hljs-comment">// A system app can be considered in the stopped state only if it was originally</span><br>            <span class="hljs-comment">// scanned in the stopped state.</span><br>            <span class="hljs-keyword">return</span> packageState.isScannedAsStoppedSystemApp() &amp;&amp;<br>                packageState.getUserStateOrDefault(userId).isStopped();<br>        &#125;<br>        <span class="hljs-keyword">return</span> packageState.getUserStateOrDefault(userId).isStopped();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><p>安卓 15 开始，又把系统应用的豁免加回来了，但有了更加精细化的控制。不仅需要满足是系统应用，同时也要满足不是被第一次开机标记为停止状态的系统应用。</p><p> <code>isScannedAsStoppedSystemApp()</code> 是用来检查一个系统应用在系统首次启动时，是否被自动置于“强制停止”（stopped）状态。</p><p>那么这个状态是怎么标记的呢？</p><h3 id="哪些应用会被标记？"><a href="#哪些应用会被标记？" class="headerlink" title="哪些应用会被标记？"></a>哪些应用会被标记？</h3><p>adb可以通过 <code>dumpsys package 包名 | grep isScannedAsStoppedSystemApp</code>来查看</p><p>主要看<code>PackageSetting</code> 的<code>setScannedAsStoppedSystemApp</code> 的调用关系</p><pre><code class=" mermaid">classDiagram    direction BT        %% 定义接口    class PackageState &#123;        &lt;&lt;interface&gt;&gt;    &#125;    class PackageStateInternal &#123;        &lt;&lt;interface&gt;&gt;    &#125;        %% 定义类    class SettingBase    class PackageSetting    %% 描述关系    PackageState &lt;|-- PackageStateInternal      SettingBase &lt;|-- PackageSetting    PackageStateInternal &lt;|.. PackageSetting</code></pre><p>最后确认为扫描系统 apk 时添加了<code>SCAN_AS_STOPPED_SYSTEM_APP</code> 的扫描标志位的应用会标记为停止状态。</p><p><a href="http://xrefandroid.com/android-15.0.0_r1/xref/frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java">InstallPackageHelper.java - OpenGrok cross reference for &#x2F;frameworks&#x2F;base&#x2F;services&#x2F;core&#x2F;java&#x2F;com&#x2F;android&#x2F;server&#x2F;pm&#x2F;InstallPackageHelper.java</a></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">private</span> Pair&lt;ScanResult, Boolean&gt; <span class="hljs-title function_">scanSystemPackageLI</span><span class="hljs-params">(ParsedPackage parsedPackage,</span><br><span class="hljs-params">            <span class="hljs-meta">@ParsingPackageUtils</span>.ParseFlags <span class="hljs-type">int</span> parseFlags,</span><br><span class="hljs-params">            <span class="hljs-meta">@PackageManagerService</span>.ScanFlags <span class="hljs-type">int</span> scanFlags,</span><br><span class="hljs-params">            <span class="hljs-meta">@Nullable</span> UserHandle user)</span> <span class="hljs-keyword">throws</span> PackageManagerException &#123; <br>  <br>        <span class="hljs-comment">// A new application appeared on /system, and we are seeing it for the first time.</span><br>        <span class="hljs-comment">// Its also not updated as we don&#x27;t have a copy of it on /data. So, scan it in a</span><br>        <span class="hljs-comment">// STOPPED state.</span><br>        <span class="hljs-comment">// We&#x27;ll skip this step under the following conditions:</span><br>        <span class="hljs-comment">//   - It&#x27;s &quot;android&quot;</span><br>        <span class="hljs-comment">//   - It&#x27;s an APEX or overlay package since stopped state does not affect them.</span><br>        <span class="hljs-comment">//   - It is enumerated with a &lt;initial-package-state&gt; tag having the stopped attribute</span><br>        <span class="hljs-comment">//     set to false</span><br>        <span class="hljs-comment">//   - It doesn&#x27;t have an enabled and exported launcher activity, which means the user</span><br>        <span class="hljs-comment">//     wouldn&#x27;t have a way to un-stop it</span><br>        <span class="hljs-keyword">final</span> <span class="hljs-type">boolean</span> <span class="hljs-variable">isApexPkg</span> <span class="hljs-operator">=</span> (scanFlags &amp; SCAN_AS_APEX) != <span class="hljs-number">0</span>;<br>        <span class="hljs-keyword">if</span> (mPm.mShouldStopSystemPackagesByDefault<br>                &amp;&amp; scanSystemPartition<br>                &amp;&amp; !pkgAlreadyExists<br>                &amp;&amp; !isApexPkg<br>                &amp;&amp; !parsedPackage.isOverlayIsStatic()<br>        ) &#123;<br>            <span class="hljs-type">String</span> <span class="hljs-variable">packageName</span> <span class="hljs-operator">=</span> parsedPackage.getPackageName();<br>            <span class="hljs-keyword">if</span> (!<span class="hljs-string">&quot;android&quot;</span>.contentEquals(packageName)<br>                    &amp;&amp; !mPm.mInitialNonStoppedSystemPackages.contains(packageName)<br>                    &amp;&amp; hasLauncherEntry(parsedPackage)) &#123;<br>                scanFlags |= SCAN_AS_STOPPED_SYSTEM_APP;<br>            &#125;<br>        &#125;<br>&#125;<br></code></pre></td></tr></table></figure><p>根据函数的注释，一个应用会被标记为“停止的系统应用”（Scanned As Stopped System App）需要满足以下<strong>所有条件</strong>：</p><ol><li><p><strong>是系统应用</strong>：即系统标记为<code>ApplicationInfo.FLAG_SYSTEM</code> 的应用。</p></li><li><p>在core&#x2F;res&#x2F;res&#x2F;values&#x2F;config.xml 配置config_stopSystemPackagesByDefault为 true，默认启用。</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment">&lt;!-- Whether system apps should be scanned in the stopped state during initial boot.</span><br><span class="hljs-comment">    Packages can be added by OEMs in an allowlist, to prevent them from being scanned as</span><br><span class="hljs-comment">    &quot;stopped&quot; during initial boot of a device, or after an OTA update. Stopped state of</span><br><span class="hljs-comment">    an app is not changed during subsequent reboots.  --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">bool</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;config_stopSystemPackagesByDefault&quot;</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">bool</span>&gt;</span><br></code></pre></td></tr></table></figure></li><li><p>应用不存在</p></li><li><p>不是 system_server（包名为 android ）</p></li><li><p>不是 APEX 包和静态资源覆盖包（Overlay）</p></li><li><p>有启动入口 (Launcher Entry)。</p></li><li><p>没有在<code>initial-package-stopped-states.xml</code> 配置中被豁免。</p></li></ol><p><a href="http://xrefandroid.com/android-15.0.0_r1/xref/frameworks/base/data/etc/initial-package-stopped-states.xml">initial-package-stopped-states.xml - OpenGrok cross reference for &#x2F;frameworks&#x2F;base&#x2F;data&#x2F;etc&#x2F;initial-package-stopped-states.xml</a></p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-meta">&lt;?xml version=<span class="hljs-string">&quot;1.0&quot;</span> encoding=<span class="hljs-string">&quot;utf-8&quot;</span>?&gt;</span><br><span class="hljs-comment">&lt;!--</span><br><span class="hljs-comment">This XML defines an allowlist for packages that should not be scanned in a &quot;stopped&quot; state.</span><br><span class="hljs-comment">When this feature is turned on (indicated by the config config_stopSystemPackagesByDefault in</span><br><span class="hljs-comment">core/res/res/values/config.xml) packages on the system partition that are encountered by</span><br><span class="hljs-comment">the PackageManagerService for the first time are scanned in the &quot;stopped&quot; state. This allowlist</span><br><span class="hljs-comment">is also considered while creating new users on the device. Stopped state is not set during</span><br><span class="hljs-comment">subsequent reboots.</span><br><span class="hljs-comment"></span><br><span class="hljs-comment">Example usage</span><br><span class="hljs-comment">    1. &lt;initial-package-state package=&quot;com.example.app&quot; stopped=&quot;false&quot;/&gt;</span><br><span class="hljs-comment">        Indicates that a system package - com.example.app&#x27;s initial stopped state should not be set</span><br><span class="hljs-comment">        by the Package Manager. By default, system apps are marked as stopped.</span><br><span class="hljs-comment">    2. &lt;initial-package-state package=&quot;com.example.app&quot; stopped=&quot;true&quot;/&gt;</span><br><span class="hljs-comment">        Indicates that a system package - com.example.app&#x27;s initial state should be set by the</span><br><span class="hljs-comment">        Package Manager to &quot;stopped=true&quot;. It will have the same effect on the</span><br><span class="hljs-comment">        package&#x27;s stopped state even if this package was not included in the allow list.</span><br><span class="hljs-comment">    3. &lt;initial-package-state package=&quot;com.example.app&quot;/&gt;</span><br><span class="hljs-comment">        Invalid usage.</span><br><span class="hljs-comment">--&gt;</span><br><br><span class="hljs-tag">&lt;<span class="hljs-name">config</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">config</span>&gt;</span><br></code></pre></td></tr></table></figure><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><p><a href="https://blog.csdn.net/li_5033/article/details/131706447">stop应用无法收到广播问题_应用未启动接收广播-CSDN博客</a></p><p><a href="https://droidyue.com/blog/2014/07/14/look-inside-android-package-stop-state-since-honeycomb-mr1/">关于Android中App的停止状态 - 技术小黑屋</a></p><p>[PMS 第 4 篇 - PMS_DATA_SCAN_START 阶段 | Coolqi&#96;s Blog](<a href="https://lishuaiqi.top/2018/02/17/PMS4-PMS_DATA_SCAN_START/#1-3-PMS-scanPackageDirtyLI">https://lishuaiqi.top/2018/02/17/PMS4-PMS_DATA_SCAN_START/#1-3-PMS-scanPackageDirtyLI</a>)</p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;前段时间有测试反馈在安卓14 上面某系统应用恢复出厂设置后没有自启动，究竟是什么原因呢？&lt;/p&gt;
&lt;h2 id=&quot;回顾&quot;&gt;&lt;a href=&quot;#回顾&quot; class=&quot;headerlink&quot; title=&quot;回顾&quot;&gt;&lt;/a&gt;回顾&lt;/h2&gt;&lt;p&gt;Android</summary>
        
      
    
    
    
    <category term="AndroidFrameworkFeature" scheme="https://iwesley.top/categories/AndroidFrameworkFeature/"/>
    
    
    <category term="Android" scheme="https://iwesley.top/tags/Android/"/>
    
    <category term="PackageManagerService" scheme="https://iwesley.top/tags/PackageManagerService/"/>
    
  </entry>
  
  <entry>
    <title>句子里的花园:来自微博用户吹牛大王孟豪森</title>
    <link href="https://iwesley.top/article/b6477895/"/>
    <id>https://iwesley.top/article/b6477895/</id>
    <published>2025-07-17T14:44:10.000Z</published>
    <updated>2025-07-18T15:45:45.000Z</updated>
    
    <content type="html"><![CDATA[<div class="note note-success">            <p>很久很久很久以前，我经常觉得孤单，我就走到全世界最低洼的地方，大哭一场，这样不会惊动恐龙们，后来，人类把那个地方叫死海。 </p>          </div><div class="note note-info">            <p>有只小狗，它听说很远很远的地方有一座骨头山，有吃不完的骨头，它挑着行李兴冲冲就上路了，历经千辛万苦，几次差点送命，终于到了骨头山。这是一具恐龙化石，早就不能吃了。它哭了一场，但很快想到一个办法，它建了一个有趣的化石公园，门票是一根骨头。——不要放弃，生活总会用它的方式回报我们。 </p>          </div><div class="note note-success">            <p>我的冰箱制冷太强，把时间都冻住了，现在还是妇女节。女士们还可以嚣张一会儿。 </p>          </div><div class="note note-info">            <p>你光速离去，我龟速追赶，我还是追的上你，你信么？因为我知道什么叫永远。 </p>          </div><div class="note note-success">            <p>海笑是海哭的声音，海肯定是得了精神分裂症，我往海里撒点镇静剂，它就安静了。 </p>          </div><div class="note note-info">            <p>爱就是地震来了你快走，我帮你挡住海啸；相信爱就是我留下来陪你，反正你挡得住。 </p>          </div><div class="note note-success">            <p>吹牛大王公告，发字第004号：催眠灯，挂在床头，到了睡眠时间会自动变暗，以柔和的光线带您入梦；再睡不着，会散发出沁人心脾的花香助眠；再睡不着，会播放轻柔的晚安音乐；还睡不着，灯会自动掉下来把你砸晕。 </p>          </div><div class="note note-info">            <p>你伤害了我，我就给蚊子装上GPS，只咬你。 </p>          </div><div class="note note-success">            <p>被女朋友骂了，说好她一吹哨子，我五分钟之内必到，结果用了六分钟。可我是从太阳跑回来的啊！光也要八分钟啊！鞋都跑掉了！砸到月亮上多一个环形山，科学家又要嚷嚷2012了！结果就是为了看你睫毛膏有没有花！专情的人你伤不起！有木有！ </p>          </div><div class="note note-info">            <p>想到一个很严肃的问题，如果猫真的会飞，一定天下大乱。它们会糟蹋每一棵树，尸体挂满电线和高压电塔，飞得低一点的鸟都会进化出鹰一样的利喙和雨燕一样的速度，它们还会半夜敲你的窗户要吃的，大摇大摆刨掉你阳台上的花，钻进花盆睡觉……感谢主。 </p>          </div><div class="note note-success">            <p>昨天参加了一个PARTY，把热闹打包，回来分成四份放冰箱，太闲的时候拿出来用。 </p>          </div><div class="note note-info">            <p>熄灯一小时，不如把全世界的灯都打开一小时，在夜空看，地球是个发出柔和光线的小煤球。 </p>          </div><div class="note note-success">            <p>什么叫胸怀大志？同样是在地上刨坑，有的人要种树，有的人要打井，有的人要钻石油，有的人只是要解大手，我呢，要把地球做成保龄球。 </p>          </div><div class="note note-info">            <p>迄今为止所有水变油的发明思路都错了，重要的不是让别人相信水可以变成油，而是让车相信，给它加的就是汽油，所以只需要建造一个一模一样的加油站，价钱啦标号啦都一样，大家交易的时候也得说“加多少油？”但油枪里出来的是水，骗过车才是最重要的，我试验过，它们都装着一箱水高高兴兴跑了几百公里。 </p>          </div><div class="note note-success">            <p>当我还是狮身人面像的时候，把每一次对你的思念，变成一个水分子，后来，我就有了一滴眼泪。 </p>          </div><div class="note note-info">            <p>她走了，笑容凝固在空气中。如果你穿过那个路口，碰到她的笑容，一定让它留在脸上，那是世界上最美丽的表情。 </p>          </div><div class="note note-success">            <p>我写了个最伟大的悲剧，却无法排演，剧本哭的把字都洇湿了。 </p>          </div><div class="note note-info">            <p>苹果排队点卯：亚当夏娃吃的苹果、砸牛顿的苹果、乔布斯的苹果、挑起特洛伊群殴的金苹果，白雪公主啃过的毒苹果，“大苹果”纽约……都在我水果筐里，我先吃哪个捏？ </p>          </div><div class="note note-success">            <p>一个小女孩非要见她的奶奶，我只好把奶奶从天上找来，说好就一晚上，小女孩跟我商量，能不能借用我的梦一下，她们在我梦里第四层相聚，滑堕到潜意识的边缘，一晚上就是五十年……我能说什么呢？晚安，诸位。 </p>          </div><div class="note note-info">            <p>还记得年少时的猛犸，没有猩猩的夜里，维尼我受冷风吹。——这是我给动物园写的歌词，真好，要是嘴够得着，我就亲自己一口。 </p>          </div><div class="note note-success">            <p>我在太平洋上插了个红绿灯，本来想疏导鱼群，可海水见红灯也停了，后浪叠前浪已经摞了两千多米，怎么办啊，我可不想再来一场海啸！ </p>          </div><div class="note note-info">            <p>愚人节大伙儿一起合伙骗太阳吧，所有灯都开着，出门打手电筒，假装撞在电线杆上，然后大骂路灯怎么不亮，情侣们在树后卿卿我我，说没人看见，组织人在湖心岛冲着太阳赏月，白领们出门看看天回去接着睡觉。看能不能把它弄疯。 </p>          </div><div class="note note-success">            <p>长胖了，每回坐飞机天文学家都以为发生了日食。 </p>          </div><div class="note note-info">            <p>假如生活抛弃了我，我就去做全世界最开心的垃圾。 </p>          </div><div class="note note-success">            <p>美丽的夫人参观我的酒窖，问为什么所有的酒瓶子都横七竖八躺着，跟刚打过保龄球似的。我说因为酒太好，它们都醉了。 </p>          </div><div class="note note-info">            <p>世界自闭症日，我的九个人格举办选秀大赛，看谁最自闭，没赶上报名的那个赢了。 </p>          </div><div class="note note-success">            <p>为应对北京停车费暴涨，本大王特推出停车服务，方法是先用万吨水压机把您的爱车压成薄片，取车时本大王亲自把车吹回原状，保证车里所有东西完好如初，宠物孩子都能吹的不走样，收费低廉空间有限。当然，如果您想销毁什么，也可偷偷告诉我…… </p>          </div><div class="note note-info">            <p>日本警方宣布抓到了一个非常危险的恐怖分子，他带了一筐蜥蜴在前往福岛的路上被警方截获，警方宣称此人计划让蜥蜴受到核辐射，变成哥斯拉，对日本全境发动恐怖袭击。在他身上还搜到一辆玩具汽车，他辩称这是给儿子的生日礼物，日本警视厅说你以为我们没看过变形金刚么？ </p>          </div><div class="note note-success">            <p>我在海边钓鱼，好多人围观，说我钓了条鲸鱼，那是我的鱼饵好不好。 </p>          </div><div class="note note-info">            <p>明天要做个大媒，把蜘蛛侠和蜘蛛精撮合到一起，头一回张罗跨国恋，有点紧张。一个住在纽约，一个住在盘丝洞，一个成天出风头，一个和孙悟空有点扯不清楚，怎么把话说周到，是个问题。 </p>          </div><div class="note note-success">            <p>清明节，怀念我的爷爷，小时候，爷爷指着天上对我说，我们的职责就是让天空飘满牛，只要人们还能看到一线天空，就是我们的失败。我说，那他们怎么分辨白天和黑夜呢。爷爷说，我们吹奶牛，让他们同时拥有白天和黑夜。 </p>          </div><div class="note note-info">            <p>失眠的时候，用一把梳子作筛子，把风拉成龙须面，月光如水好当汤，若不是星星塞牙，这餐就完美了。 </p>          </div><div class="note note-success">            <p>今天开始晨跑，跑得太快，老要停下来等自己的影子。 </p>          </div><div class="note note-info">            <p>子爵来家借东西，走进厨房大喊一声：好大的微波炉啊！我说那是冰箱。他说冰箱怎么会这么烫！我说我想她想得心滚烫，把心拿出来放进冰箱，让它冷静一下，就成这样了。 </p>          </div><div class="note note-success">            <p>我干过最没效率的事是训练蚊子叮油箱偷汽油，再到我的油箱吐出来，一百万只蚊子才偷满一箱油，而且路上两只蚊子搞对象，热情似火，肚子里的汽油着了，引燃整支编队，一片火云之后，渣都不剩。 </p>          </div><div class="note note-info">            <p>警察问我为什么在门口划个大圆圈，我说那是车位，警察问谁的，我说给朋友的，警察问朋友开什么车，我说，飞碟。 </p>          </div><div class="note note-success">            <p>小时候有一次我失踪，后来在天上找到了，原来我睡觉的时候吹了个大鼻涕泡，鼻涕泡越来越大越来越大，就把我带到天上了。 </p>          </div><div class="note note-info">            <p>12生肖都在邀请我加入它们的名人堂，但只有老鼠最有诚意，它自愿让出名额，以后属鼠的都改叫属吹牛大王的，我还在考虑。 </p>          </div><div class="note note-success">            <p>二战的时候美国人求我带领他们潜入德军敌后，但行动失败了。虽然每次都在深夜进行，但我到哪儿哪儿的公鸡都打鸣–它们以为太阳出来了。 </p>          </div><div class="note note-info">            <p>我妹妹嗲豪森小姐放牧一群云彩，有些云彩睡着了，掉到地上，变成了绵羊。 </p>          </div><div class="note note-success">            <p>公爵想吃炒疙瘩，但要吃他从没吃过的口味，我就把他洗澡时唱歌的录音放给大家听，然后炒了一大盘鸡皮疙瘩。 </p>          </div><div class="note note-info">            <p>我梦见我梦见我梦见了她。 </p>          </div><div class="note note-success">            <p>我在天上养一群奶牛，夏天下牛奶，酸雨严重的地方下酸奶，冬天下冰淇淋，雹子天下冰棍，沙尘天下冰沙，2012下蒙牛。 –2011&#x2F;04&#x2F;28</p>          </div><div class="note note-info">            <p>别人的灵魂21克，我的灵魂21公里。 </p>          </div><div class="note note-success">            <p>我做的饭太好吃了，没到嘴里就被牙齿抢着吃了，现在我的牙都撑的像象牙那么大。 </p>          </div><div class="note note-info">            <p>你是飞刀，杀死我的年华。 </p>          </div><div class="note note-success">            <p>威廉王子的新媳妇以前追我，昨天费了好大劲才说服她不要在婚礼上唱&lt;可惜不是你&gt;。 </p>          </div><div class="note note-info">            <p>你的呼吸铺成我的路，你的眼睛把我烧成灰，爱是我的伤口，你是我的盐，我戴着思念的腮，在记忆的河流里，寻找你的航标。 </p>          </div><div class="note note-success">            <p>你们每天看到的太阳其实都不是同一个，是我点击了一颗星星给美丽的夫人看，它们在天空的屏幕上被放大了而已，流星就是我的鼠标箭头。 </p>          </div><div class="note note-info">            <p>我最失败的职业经历是婚礼牧师，新娘见了我都不嫁人了。这回英国人派了007盯我，怕我去婚礼现场，007见了我也不泡妞了。 </p>          </div><div class="note note-success">            <p>我弹过的钢琴都没有黑键，它们知道我来，都化了妆打了粉底。 </p>          </div><div class="note note-info">            <p>我的妹妹嗲豪森小姐有一个酒窝，微笑时会淌出美酒，交警查酒驾，她一笑，警察就倒地不起，大醉三天，现在她常经过的路口交警都配防毒面具。 </p>          </div><div class="note note-success">            <p>我妹妹嗲豪森小姐在湖边一站，一池子鱼汤就做好了，因为湖水一见她就沸腾了。 </p>          </div><div class="note note-info">            <p>我的妹妹嗲豪森小姐如果在泰坦尼克上，悲剧就不会发生了，因为冰山一见她就会融化。 </p>          </div><div class="note note-success">            <p>申请了个qq号，别人的小企鹅闪就闪，我的每闪一次就蹦出只活的来，据说是vip待遇，我赶紧关注了一堆美女头像，结果这些美女都长发曳地地爬出来。贞子… </p>          </div><div class="note note-info">            <p>我去演话剧，所有灯光都聚集在我身上，看不见其他人，我跟舞台监督说这样不好，舞台监督说光都是正常打的，它们被吸引到你身上，我也没辙。 </p>          </div><div class="note note-success">            <p>“我客串了一把丘比特，用箭射被选中得到爱情的人。”“好浪漫。”“浪漫个P，我把他们都射死了。” </p>          </div><div class="note note-info">            <p>公爵说他打个喷嚏，方圆十里还以为地震了，我说我冲月亮打个喷嚏，月亮上就多一座环形山。 </p>          </div><div class="note note-success">            <p>我的妹妹嗲豪森小姐有一双大眼睛，她眨眼，上眼皮半个小时才能碰到下眼皮。 </p>          </div><div class="note note-info">            <p>我的妹妹嗲豪森小姐被请到国家登山队帮助强化适应性训练，因为男人只要看见她，马上会觉得大脑缺氧。 </p>          </div><div class="note note-success">            <p>捉住一段风的教程：打开相机，静候风吹过，及时按快门，注意要打开闪光灯，风知道你在给它拍照，马上会停下不动，然后用袋子把它兜住就可以了。注意按风的级数选择相应的袋子，四级以下用塑料袋，五到七级用编织袋，八到十级用军用帆布袋，十级以上用LV，非因结实，是因为风看见名牌逃跑的欲望比较小。 </p>          </div><div class="note note-info">            <p>这会儿，如果你出门看不见星星，你一定会看见我的妹妹嗲豪森小姐，星星都跑到她的眼睛里去了。 </p>          </div><div class="note note-success">            <p>我睡菠萝床单失眠了，因为我们家床单是3D的。 </p>          </div><div class="note note-info">            <p>十年前我用圆珠笔在一个小女孩手腕上画了块表，昨天她找到我，说表一周前不走了，我问那天你遇到了什么人？她说邂逅一男孩，我说这是姻缘表，遇到对的人，时间就停止了。 </p>          </div><div class="note note-success">            <p>超光速简易方案：先找个可以围绕圆心转一圈的东西，如自行车轮，然后在车轮辐的延长线上引出一根五万公里长的细线，在细线顶端放一个小灯泡，然后把车轮转一圈，注意速度保持在一秒内，这时小灯泡走过的距离是直径乘以圆周率，半径五万公里，直径就是10万公里，乘以圆周率，超过31万4千公里，耶！ </p>          </div><div class="note note-info">            <p>小时候过六一，没礼物，我和妹妹嗲豪森小姐只能把绳子扔到云上，把云当风筝放。 </p>          </div><div class="note note-success">            <p>有一年儿童节，我和妹妹嗲豪森小姐去动物园偷小长颈鹿，拿一根棍子挑着，假装是气球带回家了。 </p>          </div><div class="note note-info">            <p>（嗲豪森小姐日记）我哥哥孟豪森男爵小时候想扮成天使请女孩跳舞，但没翅膀，我说可以用鸡翅膀粘在背上代替，他照办了，晚上哭着回来。我让你用鸡的翅膀代替，不是用肯德基的鸡翅代替！ </p>          </div><div class="note note-success">            <p>假装睡着，假装睡着，装得够像，我就杀死了失眠。 </p>          </div><div class="note note-info">            <p>千万别下雨啊，不下雨，我就没法攀着雨线回到天上，就可以名正言顺旷课了。开学，开你妹！ </p>          </div><div class="note note-success">            <p>我造了一架世界上最快的电梯，你可以在楼顶把老婆推下去，然后坐电梯到一层把她接住，当然，如果你想接的话。 </p>          </div><div class="note note-info">            <p>我还想造一架更快的电梯，你进一层的时候是9点，从顶楼出来的时候是8点59分。 </p>          </div><div class="note note-success">            <p>有人问我有没在开车时睡着，我记不清了，不过倒是有几次醒来发现自己在开车。 </p>          </div><div class="note note-info">            <p>我，我的几个人格，别打架了。让我们出发吧。 </p>          </div><div class="note note-success">            <p>命运这支贱，你射穿我也罢了，还是个飞去来器，回头再来一遍。 </p>          </div><div class="note note-info">            <p>身为伟人，我每天照镜子都要使劲抬头才能看得见自己。 </p>          </div><div class="note note-success">            <p>发改委日前决定向过桥米线征收过桥费，向现场喊加油的球迷征收燃油税。 </p>          </div><div class="note note-info">            <p>雾好大，抓一把撒点白糖就有棉花糖吃。 </p>          </div><div class="note note-success">            <p>你想抽我？抽我这个风一样的男子，你就是在抽风！ </p>          </div><div class="note note-info">            <p>雪一片一片一片一片……我是涮着吃呢还是上铁板呢？ </p>          </div><div class="note note-success">            <p>我是你的雪人，虽然我只有一根胡萝卜两个煤球一把破笤帚，但至少你饿了有吃的，冷了能取暖，进门有人扫雪，渴了我就化成一盆水。我很穷，但我对你全心全意。 </p>          </div><div class="note note-info">            <p>全世界的雪，也埋不住一颗犯贱的心！雪花见我就变八瓣儿了，它们要多两只手向偶像欢呼！Good night! </p>          </div><div class="note note-success">            <p>我的妹妹，美丽的嗲豪森小姐没见过下雪，一半雪花见了她就融化了，变成雨，另一半全身冻住，变成冰雹。显然前一半是公的，后一半是母的。 </p>          </div><div class="note note-info">            <p>这个世界上最远的距离，是我的第一顿和第二顿宵夜。 </p>          </div><div class="note note-success">            <p>晚饭请了几位女士在泰坦尼克上吃火锅，这才叫海底捞嘛。 </p>          </div><div class="note note-info">            <p>别再问我为什么不去上班了！今天是国际睡眠日！ –2012&#x2F;03&#x2F;21</p>          </div><div class="note note-success">            <p>你若安好，便是晴天。为了求雨的百姓，你快挂了吧。 </p>          </div><div class="note note-info">            <p>你不爱我，这是病，得治。 </p>          </div><div class="note note-success">            <p>这一场三分球命中率只有90%，怪我弄错了规则，以为得从本方三分线出手。 </p>          </div><div class="note note-info">            <p>我用富士山点烟，等了几百年才知道是死火山，要不要把它叫醒呢。 </p>          </div><div class="note note-success">            <p>它自杀了，用毛巾在挂钩上结束了年轻的生命，它吐了很多泡沫，死的一定很痛苦，但不管我怎么搓它，它都不再冒一个泡。它在镜子上给我留下一封信，轻生的原因竟然是虽然它一天天瘦下去，我还是叫它肥皂。 </p>          </div><div class="note note-info">            <p>我的厨子很实在，我说要减肥，他就真的不给我做宵夜。我只好告诉他，我的话得反过来听。今天我想吃西梅，然后，巴塞罗那就没有然后了…… </p>          </div><div class="note note-success">            <p>海上有漩涡是我在洗衣服，大洋环流是我在洗被罩。 </p>          </div><div class="note note-info">            <p>风太大了，我设好的频道全刮乱了。 </p>          </div><div class="note note-success">            <p>土星是我媳妇，她的戒指是我给买的。 </p>          </div><div class="note note-info">            <p>听说清明节有僵尸出没，现在种豌豆还来得及么…… </p>          </div><div class="note note-success">            <p>我跑得有多快？心仪女孩喝醉了发给前男友的胡言乱语，都是我在半路拦截的，用自己的手机拦下来给她看，她以为都是发给我的，后来就从了我了。 </p>          </div><div class="note note-info">            <p>我对她说：我希望星星变成雨洒下来。她眼里闪着惊喜的光，后来，她和其它恐龙一起灭绝了。有些事情随便说说是浪漫，千万别成真。 </p>          </div><div class="note note-success">            <p>我请美丽的夫人喝酒，一人干一壶，她说我太不绅士，我说你误会了，是你一壶，我一湖。 </p>          </div><div class="note note-info">            <p>大脸大脸，你若朝南，挡住了季风；你若朝北，阻止了寒流；你一抬头，卫星还以为板块又漂移了。 </p>          </div><div class="note note-success">            <p>坦白讲我不喜欢我的星座，夜里去改改星空的形状，把天秤改成机器猫或者梦露的样子。梦露比较好吧，有流星划过裙子还能飞起来•••••• </p>          </div><div class="note note-info">            <p>我在屋顶上拴了几万个汽球，想学飞屋环游，没想到地基太结实，现在地球已经飘到冥王星轨道外了。 </p>          </div><div class="note note-success">            <p>僵尸粉也搞快闪么？谁闪我跟谁急。“不要拿一个可怜人的希望开玩笑！”——卡德罗斯，《基督山伯爵》 </p>          </div><div class="note note-info">            <p>崇拜我的人，希望你们慎重，这是一条不归路，你们会越走越远的。 </p>          </div><div class="note note-success">            <p>喝了管胶水，想粘好破碎的心，没想到粘住了胃……老天，我求你不要让我伤心而死，你就让我饿死是吗？ </p>          </div><div class="note note-info">            <p>一衰人追求我的妹妹嗲豪森小姐，嗲豪森小姐让他送只龙猫，他去了很久，满头大汗地带回来一只猫，说试了好几千只，终于找到一只聋的。 </p>          </div><div class="note note-success">            <p>我的伯爵朋友的爷爷三月份挂了，我劝他先把遗体搁冰柜里，下个月再拿出来。清明节孝子贤孙们烧冥币，烧iphone，烧二奶，咱烧真人，那些都弱爆了。 </p>          </div><div class="note note-info">            <p>天热得太快，躲在自己的影子里凉快会儿。 </p>          </div><div class="note note-success">            <p>我长的每个心眼，都是你捅的窟窿眼儿。 </p>          </div><div class="note note-info">            <p>女人都没谱，美丽的夫人说本大王只要练成豹的身材，她就答应我，我练成了，她又说海豹不是豹。 </p>          </div><div class="note note-success">            <p>想铸个井盖，一头在北京一头在洛杉矶，让太平洋成我们家下水道。 </p>          </div><div class="note note-info">            <p>我的妹妹嗲豪森小姐有把无弦琴，白天阳光是琴弦，晚上月光是琴弦，都能弹出美妙的音乐。她不在的时候我就用它拍蒜，做炸酱面吃。 </p>          </div><div class="note note-success">            <p>以前玫瑰是没有刺的，后来有些花嚷嚷着要减肥，减啊减啊就瘦成了一根刺。摘玫瑰的时候，刺扎你，是因为她们嫉妒那些没减肥的花。——致女孩们 </p>          </div><div class="note note-info">            <p>斑点狗身上的才叫斑，斑马应该叫条形马，我开的超市每样东西上都捆一只，这是工商的规定。 </p>          </div><div class="note note-success">            <p>我的好朋友王小波走了15年了，他是我见过最搞笑的人，我很想念他。“天已经晚了，饭厅里只剩了几桌客人。有一个服务员双手叉腰站在厨房门口，好像孙二娘在看包子馅。”写的多好啊，啊啊啊啊啊啊啊啊啊！ </p>          </div><div class="note note-info">            <p>我从月亮上蹦极，蹦到你的心里，地球把你转走，我就砸穿大地，我不在乎恐龙再死一次，也不在乎第二个冰川纪。宇宙是个果核，我难道没有松鼠的勇气…… </p>          </div><div class="note note-success">            <p>太阳系是一局我没有打完的台球。 </p>          </div><div class="note note-info">            <p>上次不淡定的时候，狂奔一夜，破坏了地球的微表情，招来外星人。这次不会了。主啊，给我力量沉默吧。晚安。都别梦见我，我累了。 </p>          </div><div class="note note-success">            <p>夜里睡不着，把卢沟桥的狮子都换成真的，手贱的人小心了。 </p>          </div><div class="note note-info">            <p>你的心跳，是我的地震；你的呼吸，是我的飓风；你的安睡，是我在沙漠中，沉默守护的星空。晚安。 </p>          </div><div class="note note-success">            <p>我的妹妹嗲豪森小姐有个贝壳存钱罐，今天扔进去一粒沙子，明天就能取出一颗珍珠。我扔了一把沙子和一根绳子进去，想取出珍珠项链，结果把存钱罐胀破了。 </p>          </div><div class="note note-info">            <p>我在地球上贴了邮票，等快递把我送回天枰座。 </p>          </div><div class="note note-success">            <p>100年前，我和一帮维京海盗刷夜，让仆人把多余的冰块扔到洗手间里，仆人偷懒倒在海上，其中一冰块撞上了一艘船，那艘船叫泰坦尼克。 </p>          </div><div class="note note-info">            <p>有一次遭遇空难，我毅然把降落伞让给了邻座的女士，用她饮料柠檬片上的伞逃生了。 </p>          </div><div class="note note-success">            <p>春天就是放风筝的季节啊，我怎么能想到风筝线会刮到人家的火箭呢？ </p>          </div><p class="note note-info">我发明了一部电梯，里面的数字不是楼层，是你的年龄，你按下哪个数字，它就会把你带到那时的家门口，你会遇见还很年轻的父母，或者已经长大的孩子。他们会诧异，为什么一个陌生人在门口哭泣...... 2012/04/14</p><div class="note note-success">            <p>突然降温，没暖气了，只好把家里的钻石变成煤炭来烤火。 </p>          </div><div class="note note-info">            <p>我当蜘蛛人的时候，专业擦洗卫星，喜欢在卫星上刻小王八什么的，还把卫星的正式名字擦掉，写上喜欢的女孩的名字。想她的时候就抬头，虽然看不见，但知道她在哪儿。 </p>          </div><div class="note note-success">            <p>如果脑电波真的带电，你早被我想死了。晚安。 </p>          </div><div class="note note-info">            <p>我在每个脚印里洒下一粒种子，等它们长成参天大树，把树砍掉，为师的梅花桩大阵就布成了。 </p>          </div><div class="note note-success">            <p>人类出现之前，我和月亮玩跷跷板打发时光。 </p>          </div><div class="note note-info">            <p>我的轮胎是神户牛皮做的，到目的地正好牛皮磨穿，里面的牛肉烫熟，拿把小刀就可以割着吃了。  </p>          </div><div class="note note-success">            <p>十全十美如我是很痛苦的，因为不再有奋斗目标。 </p>          </div><div class="note note-info">            <p>小时候我在课桌上给她刻了张唱片，她说很好听。我说将来我会刻一张世界上最大的唱片给你，她说：“那我就嫁给你。”后来她和别人结婚了，婚礼上她对我说：“你没有给我刻世界上最大的唱片哦。”走的时候我留了张字条：“到土星环上看看。”（晚安。）–2012&#x2F;04&#x2F;16 </p>          </div><div class="note note-success">            <p>小时候我骗我妹妹嗲豪森小姐说每天早上要有人叫太阳起床，太阳一次忘了起床，就永远是黑夜了。后来我带她去南极偷企鹅蛋，我喝醉了，喝醉的时候，极夜刚开始。半年后，被她摇醒了。她高兴地说：“我叫了半年，它终于起床了！”（晚安） </p>          </div><div class="note note-info">            <p>有时候累了，就让影子起来走，我躺下。 </p>          </div><div class="note note-success">            <p>打雷是王母娘娘逮小三，闪电是记者在偷拍。真正的冒险家，从不想征服沙漠或跨越高山，只想去翻邻居的墙。晚安。 </p>          </div><div class="note note-info">            <p>早上和女友遛弯，看见一只猫咪溺水，我摘下女友腰上的游泳圈，猫咪得救了。我对女友说：“看见了么露丝，当初杰克真心可以活下来的。” </p>          </div><div class="note note-success">            <p>小时候我和妹妹嗲豪森小姐每天在家画毛票，去路口的老奶奶那儿买糖，每次都能骗过她，我俩以为自己是画画天才，长大了才发现不是的。 </p>          </div><div class="note note-info">            <p>你是水银海上的巨浪，扑灭了太阳，把我拍成肉酱，我变成了一封信，还盖着心形的章。晚安。 </p>          </div><div class="note note-success">            <p>我叔叔是个财迷，每次被婶婶打破鼻子，就飞奔去卖血。 </p>          </div><div class="note note-info">            <p>我妹妹嗲豪森小姐很白，北极熊站在她旁边，别人都以为是头黑熊。 </p>          </div><div class="note note-success">            <p>有一年我环游世界，捡了只猴子。医生说它失忆了。它的确行为异常，我们每经过一个瀑布，它就不管不顾往里跳，有时头破血流，有时差点淹死，谁也不知道它为什么这么做。一天我看着它头顶的印记，突然知道它是谁了。我中止旅行，把它送回了那座山。 </p>          </div><div class="note note-info">            <p>吃完早饭去跳水，十米高台，快扎到底了才发现池子里没水，赶紧朝池底吹了口气，连续6个后空翻才回到跳台上。 </p>          </div><div class="note note-success">            <p>我吞了只蜘蛛，让它在我心里结网，假装你从未来过；结果这只文艺女蜘蛛把它的心上人织在我心里，现在我每天看着各种版本的《蜘蛛侠》流口水。 </p>          </div><div class="note note-info">            <p>困了，骑肥皂泡去云里，睡个饱觉。 </p>          </div><div class="note note-success">            <p>我去过一个星球，那里的闪电会凝成固体，从几万米高空落下来，星球上全是各种形状的闪电，新的砸到旧的上面，发出电火花和类似工地的动静。我捡了两根最小的送给妹妹嗲豪森小姐，她别在头发上，再也不怕手机没电了。 </p>          </div><div class="note note-info">            <p>夏天的时候我和妹妹嗲豪森小姐会缩成一棵草那么高，去和青蛙赌钱，荷叶作赌桌，捉一星到六星瓢虫粘在一起当骰子，谁输了就去吓唬池塘边的情侣。青蛙的办法是往女孩脖子里跳，我和妹妹就假装警察大喊一声“往哪儿摸呢！”听说有几个吓出了后遗症，我们就不玩了。 </p>          </div><div class="note note-success">            <p>夸父其实是送快递的，如果不能日落之前送到，手里的货物就得免单；后羿其实是城管，为配合修建银河高速公路，强拆了九个太阳；女娲其实是美容医院的，拿五色石补天是宇宙最大的整形广告；我骑着流星在你们头顶乱窜，其实是发小广告的，天秤座新开盘了，欲购从速。 </p>          </div><div class="note note-info">            <p>我发明了一种汽车产房，两辆车开进去，第二天就能生下一个孩子，一辆奔驰和一辆宝马有很大机会生下好车比如英菲尼迪；一辆夏利和一辆松花江很可能就生下个奥拓；但也会基因突变，比如夏利和松花江配一百次能出个兰博基尼；如果奔驰配夏利，生出什么完全没谱，大多数是不能要的杂牌，门当户对很重要啊。 </p>          </div><div class="note note-success">            <p>包公额头上一个月牙就生具异相不是凡人了，我舅舅脸上一整条银河呢，别人还是只叫他大麻子。这个社会怎么了？ </p>          </div><div class="note note-info">            <p>我去过一个星球，那里雨是从地面往天空下，你哭的时候，眼泪飞上天空变成一朵云，这朵云会找到你的另一半，把眼泪洒到他身上。不管隔多远，他都会来找到你。 –2012&#x2F;04&#x2F;24</p>          </div><div class="note note-success">            <p>我养过一小猫，立志要做世界上第一只抓到鲨鱼的猫，天天在海边蹲着，此事轰动鲨鱼界，发展出好几门产业，有“围观傻猫一日游”旅行团，有赌小猫哪天放弃的博彩公司。小猫一直没放弃，鲨鱼们感动了，选了只拍过戏的鲨鱼，假装被小猫抓住咬死，横“尸”沙滩。小猫高高兴兴走了，鲨鱼们给小猫立了座铜像。 </p>          </div><div class="note note-info">            <p>人类出现之前，我每晚开演唱会，假装星星是观众席上的打火机。 </p>          </div><div class="note note-success">            <p>岁月是人生的说明书，我好不容易读懂，已经要挂了。 </p>          </div><div class="note note-info">            <p>夏天到了，我在领地四个角发射了四颗卫星，挂蚊帐。 </p>          </div><div class="note note-success">            <p>我白天假装是你的好朋友，晚上入睡前都攥着戒指，等着梦见你。晚安。  –2012&#x2F;04&#x2F;29</p>          </div><div class="note note-info">            <p>结婚的人真多啊，刚才参加一个婚礼，两对新人用一个厅，客人拼桌，台上俩司仪说相声，其中一家人安排了个环节，新人熄灯拥吻。等开灯发现吻错了，俩新郎抱一块，后来就乱了，我趁乱抢回红包回家了。 </p>          </div><div class="note note-success">            <p>我参加过的最极品的婚礼是在麦当劳，92年吧，那时候刚有麦当劳，车队、花门、气球、彩带什么都有，一对新人山盟海誓之后，宾客们排队去点餐。 </p>          </div><div class="note note-info">            <p>我把月亮改成声控的，你醒的时候它陪着你，你困了，拍拍手，只留下满天的星星。晚安。  –2012&#x2F;05&#x2F;01</p>          </div><div class="note note-success">            <p>每次看到我的猫，我都会不由自主思考生活的意义：原来完全没有意义也是一种意义。 </p>          </div><div class="note note-info">            <p>那年我去旅行，在小树林里发现一头自卑的黑熊，浆果绝收，它已经快饿死了，但死活不肯离开树林。我好说歹说带它出来，后来我不小心掉河里，它跳下去把我救上来。我看着它发呆，它说：“明白我为什么自卑了吧，我从小有白癜风，用颜料遮住的。别歧视我好吗？”——这个二货，它从来没见过自己的同类…… </p>          </div><div class="note note-success">            <p>给我的龙设计食盆，画图遇到问题，负数阶的球谐函数按理可由正数阶函数对 z-轴转 90&#x2F;m 度得到，可代入拉普拉斯方程后，无法归一化因子，删掉虚数单位也不行。这必然导致我的龙把水喝到鼻子里，郁闷，睡了。有明白的给我留言吧，想引入玻色.爱因斯坦积分的就别费劲了。试过了，没用。 </p>          </div><div class="note note-info">            <p>长城其实是烧烤一条街，古时候游牧民族负责牛羊肉，汉人负责场地——那些箭垛子明摆着是架烤串的，木炭一边出一半。隔一段时间就开个大趴替，在最大的烧烤台上烤全羊，怕来的人太多，骗大伙说是在打仗，点狼烟呢。 </p>          </div><div class="note note-success">            <p>我没放风筝，我在钓龙。 </p>          </div><div class="note note-info">            <p>我没放风筝，我在给天空贴创可贴。 </p>          </div><div class="note note-success">            <p>小时候保姆给我和妹妹讲故事，月亮本来身材很苗条，后来怀孕了，肚子就越来越圆，到最圆的时候，开始分娩，生小星星，流产的就是流星。星星爹是太阳，太阳抛妻弃子，只在白天出现，到晚上就躲了，只有月亮和孩子们孤独地挂在天上。她说的声情并茂，我想月亮逊弊了，这种男人还每个月让它搞大一次肚子。 </p>          </div><div class="note note-info">            <p>有一年雨夜，一个面罩轻纱的女郎来敲门，自称是个真正的公主。我想起豌豆公主的故事，就在床上放了粒豌豆，上面摞了无数床垫和鸭绒被。半夜我被凄厉的尖叫惊醒，她冲进来，嘶哑地问屋里为什么有豌豆。我正在高兴，突然一股凉意升起：“能被豌豆伤害的，不一定是公主，也可能是……”她缓缓撩开面纱……  </p>          </div><div class="note note-success">            <p>给美丽的夫人的情书写完了，用墨鱼汁写在羊皮上，用了二十只螃蟹做订书钉，她就算不接受我的心，至少可以扔进锅里，不至于亏待自己的胃。 </p>          </div><div class="note note-info">            <p>如果和日本打赢了，我就在富士山上罩个大铜烟囱，绕山挖一圈河，扔导弹把火山点着，等河水开了，往里扔神户牛肉、鱼片、葱段、辣椒、白菜、豆腐、粉丝……对，就是你们，本大王的粉丝，你们坐着特制木船“鲜肉丸”，船舱里放着麻酱香油海鲜汁味噌，船桨是大木勺，想吃什么捞什么……  –2012&#x2F;05&#x2F;21</p>          </div><div class="note note-success">            <p>如果你在暗恋一个人，并下决心要实现梦想，你可以来找大王。大王把“XX爱XX”刻在刚出生的大鹏鸟的翅膀上。你有两年的时间，两年之后，大鹏鸟的翅膀会长到500米宽，这行字全世界都看得见。希望那时候你觉得幸福，她觉得荣耀。 </p>          </div><div class="note note-info">            <p>我吹着笛子向你进发，星星在头顶排成一行。晚安。 </p>          </div><div class="note note-success">            <p>我的妹妹嗲豪森小姐想干掉一个专杀流浪狗的混蛋，请教我怎么在30公里外打中目标，我说30公里的狙击学问太大了，要计算光线、风速、地球自转、地球引力、空气湿度、大气扰动、生物活动等参数……刚才她说把那个混蛋狙掉了，我说谁教你的，她说很简单，做个30公里长的枪管就行了。 </p>          </div><div class="note note-info">            <p>0点之后，拨打麦当劳订餐电话，对订餐员说：请给我来一份煎饼果子，双份蛋，加千岛汁。不管对方怎么解释，你都重复这句话，挂掉再拨，再挂掉再拨，第三次的时候，会有一个悦耳的英国口音问你：“男爵殿下，您来点什么？”这是我私人独享的订餐热线，刚才点了煮菱鲆鱼浇牡蛎汁和小牛肉，你们都试试吧。 </p>          </div><div class="note note-success">            <p>绿巨人为什么是绿色的，还很生气？我请他吃刺身，说一人一半，后来我吃了所有鱼肉，他吃了所有芥末。 </p>          </div><div class="note note-info">            <p>我把每次和你的回忆切碎，装进万花筒，这样我永远有新的回忆。晚安。  –2012&#x2F;05&#x2F;24 00:49</p>          </div><div class="note note-success">            <p>有一回我和妹妹嗲豪森小姐过大峡谷，峡谷太宽过不去，我拿出口香糖吹了个无比大的泡泡，把妹妹和月亮都装进去，月亮把我们带过去了。 </p>          </div><div class="note note-info">            <p>我最潦倒的时候摆摊卖过冥币，一天一个老太太找到我，说能不能定制，别印阎王，印她的头像，我说这对您可不吉利，她说就是想给下面带个信，让他知道她想他。我答应了，她又给我一张纸条，说能不能把这个也印上，我一看密密麻麻十几条，都是我妈常跟我说的话。原来下面是她儿子…… </p>          </div><div class="note note-success">            <p>出了趟远门，帮北斗七星打架去了，近日会有陨石雨，是敌人碎尸，倒时差先睡了，晚安。 </p>          </div><div class="note note-info">            <p>这次去了不减肥会死星，星球地表是压力感应的，超重的会压垮地壳，掉到地心里当燃料；还去了瘦子让你得瑟星，地表也是压力感应，分量不够的会被弹射到大气层外当卫星，星球最盛大的节日是胖子们吃着蛋糕，拿望远镜观赏天上的瘦子。小胖子们把食物塞到炮膛里射上天，运气好的瘦子吃胖了有机会复活。 </p>          </div><div class="note note-success">            <p>我送给美丽的夫人一挺机枪，她想我的时候，把吻装进每一颗子弹，向我倾泻过来。如果我满身口红失去知觉，不要抢救我，我是爽死的。  </p>          </div><div class="note note-info">            <p>我寂寞的时候，跟回声聊天，给它讲段子，然后假装头一次听到。 </p>          </div><div class="note note-success">            <p>我的宇宙是个宏伟的肥皂泡，你是一根针。 </p>          </div><div class="note note-info">            <p>把这场雨添加到我的收藏了，下次失恋拿出来。  2012&#x2F;07&#x2F;24 00:51</p>          </div><div class="note note-success">            <p>我造了艘玻璃飞船，发射之后，就是银河里的漂流瓶，给你的话写在里面了，希望有外星人拾到。地球上我找不到答案。 </p>          </div><div class="note note-info">            <p>北京还没下雨，是我正在给每个雨点拴降落伞。 </p>          </div><div class="note note-success">            <p>经过我驯化的龙卷风，扔建筑材料进去，所过之处能盖起一座城市。 </p>          </div><div class="note note-info">            <p>如果入水后竖着游1500米，本大王有信心拿世界第一。 </p>          </div><div class="note note-success">            <p>为什么我没有活在我得到了你的那个平行宇宙里？晚安。 </p>          </div><div class="note note-info">            <p>怎样才能让地球不转？举办一个太阳系好声音，本大王上去献唱。 </p>          </div><div class="note note-success">            <p>王尔德说：人生有两大悲剧，一个是没有得到想要的东西，一个是得到了想要的东西。萧伯纳说：人生有两大悲剧，一是万念俱灰，一是踌躇满志。但本大王更喜欢这句话：“悲观主义者认为所有女人都是坏女人，乐观主义者希望这是真的。” </p>          </div><div class="note note-info">            <p>我把关于你的一切记忆都扔进黑洞了，那为什么我还要写这条微博？晚安。  2012&#x2F;09&#x2F;03 01:24</p>          </div><div class="note note-success">            <p>想把人类浪费的食物都运到北极去，浇成一个大冰山，北极熊就不会饿死了。把不爱本大王的人也浇进去。 </p>          </div><div class="note note-info">            <p>赠人肉丝，手有鱼香。 </p>          </div><div class="note note-success">            <p>“饿的时候我会摊一张足球场那么大的煎饼，上面铺满菜叶子。”“大王您改吃素啦。”“不是，菜叶子把牛羊都吸引来，一卷就可以吃了。” </p>          </div><div class="note note-info">            <p>后羿说他射下九个太阳，吹牛，实际情况是他参加相亲节目，十个太阳全灭，只有月亮没灭，他才娶了嫦娥。现在你们看到的太阳是他们害死了猪八戒，点着了冒充的，它油多嘛，也比较圆。 </p>          </div><div class="note note-success">            <p>雪是穿婚纱的雨。   2012:11:04 10:45</p>          </div><div class="note note-info">            <p>想你的时候我会点支蜡烛，把手影投到月亮上。晚安。</p>          </div><div class="note note-success">            <p>又下雪了！老天你不知道堆雪人很累的吗？你就不能直接下雪人吗？ </p>          </div><div class="note note-info">            <p>小时候本大王被抓去当童工，发给一粒粒钻石让我嚼，吹出来的泡泡挂在天上，替换那些坏掉的星星。晚安。 </p>          </div><div class="note note-success">            <p>雾太浓了，可以堆雪人。 </p>          </div><div class="note note-info">            <p>我以为我的心是铁打的，遇见你才发现，原来它是泡腾片做的。  2013:01:14 09:07</p>          </div><div class="note note-success">            <p>风大的把地球都吹跑了。 </p>          </div><div class="note note-info">            <p>幸福是欲望的暂时停止，所以一切梦想都不要变成现实。 </p>          </div><div class="note note-success">            <p>从今天开始好好练枪法、练扔雪球、练拉电线绊人，争取七个月后成功打劫圣诞老人。立此存照！[拳头]  2013&#x2F;05&#x2F;11</p>          </div><div class="note note-info">            <p>地震是寂寞的地球在用摇一摇。 </p>          </div><div class="note note-success">            <p>本大王当年养过一窝小香猪，长不大的那种，有一只长到600斤，没脸见人，躲到树林里去了，不幸树林里有整整一群狼，它谎称自己是个扑满，狼正好没有银行，把辛苦攒下的钱都存到它嘴里，它装了满满一肚子钱跑回来，成了大富翁。这个故事告诉我们，只要你有智慧，越胖越好。 </p>          </div><div class="note note-info">            <p>如果你去了冥王星，我就把太阳变成路由器。晚安。 </p>          </div><div class="note note-success">            <p>我时日无多了，香蕉都不敢买绿的。 </p>          </div><div class="note note-info">            <p>月亮是天空的处女膜，看到它，我就依然相信爱情。晚安。 </p>          </div><div class="note note-success">            <p>小时候比赛谁尿得高，本大王尿出了银河。 </p>          </div><div class="note note-info">            <p>流星是有强烈个人诉求的屌丝天使烧掉的星际大巴。 </p>          </div><div class="note note-success">            <p>伯爵说他那里的空气很差，病人手术的时候如果没有麻醉药，脑袋伸出窗外就可以了；我说我们这里的空气可以扔到嘴里嚼。 </p>          </div><div class="note note-info">            <p>我往银河扔了好多贝壳，明天所有的行星都会变成珍珠，晚安。 </p>          </div><div class="note note-success">            <p>本大王遇到过一个活了三万年的人，他说地球那时候是方的，走到边缘就会掉下去，后来人们无意中发现地下是空的，经过好几千年的努力，终于剥掉了大地的外壳，露出里面真正的地球。其实地球原本装在一个盒子里，是一个礼物，但不知道是谁送的，也不知要送给谁。 </p>          </div><div class="note note-info">            <p>我妹妹嗲豪森小姐养过一只猫，它只会往前走，不会回头也不会拐弯，我妹妹把它养在一个特制的笼子里。有一天笼子破了，它走了出去，七十年以后，我妹妹发现它趴在门口，它绕地球一圈回来了，而且它当初是往北走的，所以经过了北极和南极。所以，就算方向错了，只要你一直走，依然能得偿所愿。 </p>          </div><div class="note note-success">            <p>#那些年我们上过的当#女朋友发誓要瘦成一道闪电，后来本大王才知道真有一种闪电叫球形闪电。⚡⚡⚡[衰] </p>          </div><div class="note note-info">            <p>人类出现之前，我用小刀把月亮切成58个面的钻石。 </p>          </div><div class="note note-success">            <p>怀念在蟠桃会门口倒假票的日子，怀念和八戒降低云头看嫦娥裙底春光的日子，怀念偷二郎神家宠物狗的日子，怀念在如来佛手指上写拆的日子，可惜天上没有不散的筵席，卷支大麻，吐成云，希望灵霄中街还流传我的传说。 </p>          </div><div class="note note-info">            <p>以前我认识一颗流星，它爱上一个女孩，每天从她阳台外面飞一遍，给女孩许愿的机会。有一天它发现女孩的心愿实现了，阳台上多了个男孩，它颓了一阵，不飞了。有一天我看见它又要飞，问为什么，它说：我要给自己许一个愿。  –2013&#x2F;11&#x2F;09</p>          </div><div class="note note-success">            <p>别对流星许愿了！一个没跑到厕所就飙屎的倒霉蛋，你们觉得它有心情帮你解决问题吗？？  –2014&#x2F;04&#x2F;03</p>          </div><div class="note note-info">            <p>我小时候有一次挨打是因为骗我弟说吃肥皂泡会飞，他吃光家里所有的肥皂，从二楼跳出去了。 </p>          </div><div class="note note-success">            <p>我挺好，太阳系是一伙孤独的碰瓷党，在凌晨3点的宇宙十字街头踯躅。   –2014&#x2F;07&#x2F;22</p>          </div><div class="note note-info">            <p>想到嫦娥也正在赏月，我决定挖一个心形的大湖，一半种玫瑰，一半种胡萝卜。 </p>          </div><div class="note note-success">            <p>沙是地球的骨灰，钻石是舍利子。 </p>          </div><div class="note note-info">            <p>蜘蛛和蟑螂哪个更恶心？蟑螂。有蜘蛛侠，你能想像蟑螂侠吗？ </p>          </div><div class="note note-success">            <p>本大王认识一个超级英雄，被基因突变的蚕咬过，成了蚕侠，虽然也有吐丝技能，但行动迟缓，吐丝很慢，随身需带大把桑叶，必杀技是把自己裹起来，所以怎么也不红。看着蜘蛛侠成了大明星，他终于得了抑郁症，吐出来的是烦恼丝，大受女文青欢迎，从此不敢开心，多拧巴。 </p>          </div><div class="note note-info">            <p>本大王为防心碎，把自己的心做成橡胶的，可它还是碎了，我才知道所有的心掉在地上之前，都已经冻得像玻璃一样了。 </p>          </div><div class="note note-success">            <p>本大王去过一个古怪的地方，那里的人经常跟你说着说着话，突然浑身打战，然后就消失了。后来才知道，我进了一部手机。 </p>          </div><div class="note note-info">            <p>我用烟火截断银河，召唤来一场大雨。 </p>          </div><div class="note note-success">            <p>我当年收养过一头小鲸鱼，我们一起在海里游泳唱歌，后来它离开我找同伴去了。最近听说科学家在找一头鲸鱼，它孤独地唱了二十年，没有一头鲸回应，我猛然醒悟，就是它，它跟我学会了用人的频率唱歌，200赫兹，可鲸鱼的频率不到20，没有鲸鱼能听到它的声音。我决定放弃假期去找它。小鲸鱼，你在哪里？ </p>          </div><div class="note note-info">            <p>我认识一只小猫，它把紫菜做的保健腰带卖给鲨鱼，肚子的位置有一坨饭团，说是信息大米。然后它又把这些鲨鱼卖了，说是鲨鱼寿司，赚了很多钱。 </p>          </div><div class="note note-success">            <p>我吃光了全世界的橡皮擦，她的名字还是在我心里。晚安。  2015&#x2F;03&#x2F;01 00:28</p>          </div><div class="note note-info">            <p>一个岛爱上了另一个岛，他开始收养珊瑚虫，珊瑚虫明白他的意思。很多很多年以后，一条珊瑚礁把两个岛永远连接在了一起。 </p>          </div><div class="note note-success">            <p>还有一个岛也爱上了另一个岛，但他找不到珊瑚虫，爱情郁积在心中，心越来越烫，终于有一天，他的心猛烈地喷发了，遮天蔽日。烟雾散尽，火山灰把两个岛变成了一个岛，他们从此幸福地生活在一起，岛上铺满了钻石。 </p>          </div><div class="note note-info">            <p>我把星星装进沙漏，时间就变成了银河。晚安。  2015&#x2F;03&#x2F;03 03:30</p>          </div><div class="note note-success">            <p>我一堂哥太高了，食物落到胃里之前就饿死了。 </p>          </div><div class="note note-info">            <p>液体就是形状随容器改变的物体，所以猫是一种液体。 </p>          </div><div class="note note-success">            <p>我们的宇宙直径其实只有0.7光年，人类看见的浩瀚星空是全息影像，我们生活在外星人制造的一枚巨蛋中，外面真正的宇宙图景是我们完全无法想象的，人类将在2033年发现这一事实，并组织舰队试图冲破牢笼。  </p>          </div><div class="note note-info">            <p>我把关于你的记忆从动脉里抽出来，想你的时候再输回去，我就这样成了瘾君子。 2015&#x2F;03&#x2F;14 01:10</p>          </div><div class="note note-success">            <p>冰淇淋是南极工厂的雪人制造出来的，准确说是拉出来的，正常的时候是冰淇淋，大便干燥的时候是冰棍，闹肚子的时候是奶昔，半稀半干的时候是珍珠奶茶，闹得最厉害的时候会拉出一杯热巧克力，这时雪人的热量耗尽，就挂了。不喝热巧，就没有杀害。 </p>          </div><p class="note note-info">有一年冬天，出现了一个正能量雪人，又热情又滑稽，所有见过它的人都开心得不得了，是个荷尔蒙版的大白。后来才知道它是一帮毒贩子用海洛因堆成的。</p><div class="note note-success">            <p>一条道走到黑，再走几个小时，天就亮了。 2015&#x2F;03&#x2F;17 23:52</p>          </div><p>自从以后的微博都不是他写的了。<a href="https://weibo.com/1658197767/4897263031683749">https://weibo.com/1658197767/4897263031683749</a></p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;div class=&quot;note note-success&quot;&gt;
            &lt;p&gt;很久很久很久以前，我经常觉得孤单，我就走到全世界最低洼的地方，大哭一场，这样不会惊动恐龙们，后来，人类把那个地方叫死海。 &lt;/p&gt;
          &lt;/div&gt;



&lt;div</summary>
        
      
    
    
    
    <category term="转载" scheme="https://iwesley.top/categories/%E8%BD%AC%E8%BD%BD/"/>
    
    
    <category term="诗" scheme="https://iwesley.top/tags/%E8%AF%97/"/>
    
    <category term="collection" scheme="https://iwesley.top/tags/collection/"/>
    
  </entry>
  
  <entry>
    <title>重读《百年孤独》后的回忆</title>
    <link href="https://iwesley.top/article/6eef96b2/"/>
    <id>https://iwesley.top/article/6eef96b2/</id>
    <published>2025-07-17T13:47:54.000Z</published>
    <updated>2025-07-17T13:54:16.000Z</updated>
    
    <content type="html"><![CDATA[<p>多年以后，面对电子相册的往年今日，面对从未丢失却沉寂已久的短信，他会清晰地回忆起十年前那段旧时光——在人来人往的教室长廊里与她欢乐交谈，铃声响起仍然感觉意犹未尽，青春的低语混合着尘埃的微光飘浮；在黄色的信纸上写下过书籍读后感，写下过彼此的美好祝愿与鼓励，也写下过对生活的感悟，黑色的墨迹承载了一段青春舞曲；在上学前，他有意无意地望向窗外，看到她的身影经过，心里飘忽不定；在一个无常的周末，他坐在教室里曾重复听着某一首歌，内心充满着纠结，直到今天再次唱起仍然感慨万千。后来，他意识到过分的关心可能引起了她的逃避和无心的无视，他决定画好界限。在一个夜晚相聚后，他骑自行车送她回家，可能是因为大风或者沙子进了眼睛，有热泪流了出来，他感觉后面可能再也没有见面的机会了。</p><p>此后的过年期间，有一次他们在超市相遇，好像陌生人一样，彼此问候后就此别过。还是太年轻，如果可以重来，他们可以一起坐下来喝杯奶茶，聚聚旧。他和朋友的聚会中，还是能经常听到她的消息，他不作声，只是聆听。</p><p>孤独来自脆弱的敏感。</p><p>现在，他们不经常联络了。年初他看着她毕业的照片时，看到了和十年前一样纯真动人的笑容，岁月掩盖不住她明亮的眼睛，祝愿她平安快乐！</p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;多年以后，面对电子相册的往年今日，面对从未丢失却沉寂已久的短信，他会清晰地回忆起十年前那段旧时光——在人来人往的教室长廊里与她欢乐交谈，铃声响起仍然感觉意犹未尽，青春的低语混合着尘埃的微光飘浮；在黄色的信纸上写下过书籍读后感，写下过彼此的美好祝愿与鼓励，也写下过对生活的感悟</summary>
        
      
    
    
    
    <category term="随笔" scheme="https://iwesley.top/categories/%E9%9A%8F%E7%AC%94/"/>
    
    
    <category term="随笔" scheme="https://iwesley.top/tags/%E9%9A%8F%E7%AC%94/"/>
    
  </entry>
  
  <entry>
    <title>说说9月8号以来的短学期</title>
    <link href="https://iwesley.top/article/daa12744/"/>
    <id>https://iwesley.top/article/daa12744/</id>
    <published>2025-07-06T14:45:52.000Z</published>
    <updated>2025-07-06T15:02:16.000Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>翻看便签看到了一篇旧文，写于2017年9月16号下午1点35分</p></blockquote><p>嗯……或者可以说是一次“假研究生”“假学长”的经历……，因为他们是准备读大三大四的真学长学姐……</p><p>这个短学期主要是由我们实验室承担的一个pic单片机短学期学习任务，我们开始是给他们讲讲课，讲一些软件操作和一些基本问题，后来基本就是一个助教的角色，辅助他们解决一些问题，最后再负责验收一下就ok了……</p><p>这期间发生了两次尴尬的事，一次是老师介绍我们时，说我们是研究生😂，当时的反应就是尴尬地笑笑……第二次尴尬发生在今天，有一位同学问我一些关于研究生导师的问题，我勉强说了一些，最后还是否认了这个身份，勉强地绕出去了，也没说是大一的……</p><blockquote><p>嗯……让我想起了老罗的一个故事<br>我小的时候呢，脸皮厚叫“脸皮厚”，无耻叫“无耻”，现在都叫心理素质好。(lol…) 真奇怪！像我跟几个朋友去爬山，然后下来累了，在那个长凳上，我们5、6个坐成一排休息，然后大家拿了一些瓜子，然后拿了个塑料袋，嗑完了瓜子就扔到塑料袋里去了，但是吃完手不黑了吗？于是大家掏出一点纸巾，互相分，然后把手擦一擦。然后把那个就放到座位上了，结果一阵风一吹呢都刮地上了，不是故意扔地上的，被刮到地上去了，然后坐在那儿没走嘛，一懒，暂时就没拣，都下了山，挺累的。结果清洁人员就过来了，说“哎～这个纸是不是你们给扔的啊？”然后我脸一下就红了，然后他们几个都没事，(lol…) 然后我说“是”，然后他说“罚款”，我说“好”，然后我就把罚款交了，我又自己把那纸给拣起来了。然后那个罚款的人走了以后，他们几个人就看着我说“哎，老罗你怎么心理素质那么差？”(lol…) “不承认不就行了么？”但是你脸已经红了，所以你不承认也不行。“你怎么心理素质那么差？”好我就奇怪了，我才知道“心理素质”是这个意思。过去我们叫“无耻”，现在叫“心理素质”。明明是你干的，你怎么能心理素质那么好呢？(lol…) 好……这是……题还没讲呢！(lol…) 向大家郑重道歉！(lol…)</p></blockquote><p>哎呀，诚实是一个奢侈的品质！</p><p>短学期总体来说感觉还是不错的，虽然头三天可能是因为生物钟没调节过来，连续失眠，精神不好，但后来慢慢就很快睡着了……给他们讲课，辅助他们，有种回到高中帮别人解题的感觉，对，那种感觉特别美好！哈哈！</p><p>哦，期间实验室举行了“孵化器杯”的第一届羽毛球比赛，那天是9月9号，那天由于一些人弃赛，我直接就跳过第一轮，直接晋级了……下午，连打了三局，都比较幸运惊险地获胜了，我都没想到得到了一等奖😜……虽然学了一学期的羽毛球，但感觉高远球这些都没怎么运用，还是任重道远……</p><p>那些年，曾经在孵化器杯上走过这么一个血肉之躯……<img src="https://cdn.jsdelivr.net/gh/wesley666/picgo/img2025/20250706225434744.jpg" alt="Notes_1751813220024"></p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;blockquote&gt;
&lt;p&gt;翻看便签看到了一篇旧文，写于2017年9月16号下午1点35分&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;嗯……或者可以说是一次“假研究生”“假学长”的经历……，因为他们是准备读大三大四的真学长学姐……&lt;/p&gt;
&lt;p&gt;这个短学期主要是由我们实验室承</summary>
        
      
    
    
    
    <category term="随笔" scheme="https://iwesley.top/categories/%E9%9A%8F%E7%AC%94/"/>
    
    
    <category term="随笔" scheme="https://iwesley.top/tags/%E9%9A%8F%E7%AC%94/"/>
    
  </entry>
  
</feed>
