乱码三千 – 分享实用IT技术

乱码三千 – 码出一个新世界


  • 首页

  • 归档

  • 搜索

关于android scheme跳转配置中pathPattern的使用

发表于 2021-06-03

Scheme协议在Android中使用场景

  1. H5页面和Native页面的交互

  2. 客户端获取push消息中后,点击消息跳转到APP内部页面

  3. APP根据URL跳转到另外一个APP指定页面

  4. 外部浏览器唤醒App

Scheme协议的使用

  1. 场景一 外部浏览器唤醒app

以app://test/good?goodsId=3这个内链为例, 假设浏览器中点击该内链需要跳转到应用的指定Activity

那么,首先在清单文件中对指定Activity进行intent过滤配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<activity
android:name=".ui.login.LoginActivity"
android:screenOrientation="portrait">
<intent-filter>
<!--可以根据用户的数据类型,打开相应的Activity-->
<action android:name="android.intent.action.VIEW" />
<!--界面可以被隐式调用-->
<category android:name="android.intent.category.DEFAULT" />
<!--界面可以通过浏览器的连接启动-->
<category android:name="android.intent.category.BROWSABLE" />
<!--协议部分,主要是配置scheme和host-->
<data
android:path="/good"
android:host="test"
android:scheme="app" />
</intent-filter>
</activity>

然后在Activity的onCreate方法中进行参数的获取和逻辑的处理:

1
2
Uri data = getIntent().getData();
String param = data.getQueryParameter("goodsId");//获取指定key下的参数

最后测试跳转即可

  1. 场景二 应用内部H5交互(页面跳转)

    还是以app://test/good?goodsId=3这个内链为例, 假设WebView中点击该内链需要跳转到应用的指定Activity

    首先还是在清单文件中配置,如上

    然后配置webview:

    1
    2
    3
    4
    override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
    startActivity(Intent(Intent.ACTION_VIEW, url.toUri()))
    return true
    }

    因为webview属于开发者自定义, 因此内链跳转逻辑需要在shouldOverrideUrlLoading方法中自行处理

  2. 场景三 应用内部H5交互(非页面跳转)

    有时候需求不单单是页面的跳转, 可能还涉及到其他ui或者逻辑的交互, 比如跳转到支付宝失败后弹出弹窗等等, 这个时候,我们需要在shouldOverrideUrlLoading方法中进行不同scheme的处理:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
    if (url.startsWith("alipay")) {
    try {
    startActivity(Intent(Intent.ACTION_VIEW, url.toUri()))
    } catch (e: Exception) {
    e.printStackTrace()
    AlertDialog.Builder(requireContext())
    .setMessage("未检测到支付宝客户端,请安装后重试。")
    .setPositiveButton("") { _, _ ->
    startActivity(
    Intent(
    Intent.ACTION_VIEW,
    "https://d.alipay.com".toUri()
    )
    )
    }
    .setNegativeButton("取消", null).show()
    }
    }
    return true
    }
  3. 场景四 应用内Activity之间的跳转

    首先依然在清单文件中配置

    然后使用隐式跳转:

    1
    startActivity(new Intent(Intent.ACTION_VIEW,Uri.parse("`app://test/good?goodsId=3`")))

多个不同scheme跳转同一个页面

只需要在清单文件增加多个data标签即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<activity
android:name=".ui.login.LoginActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data
android:path="/good"
android:host="test"
android:scheme="app" />


<data
android:host="test2"
android:scheme="app" />
</intent-filter>
</activity>

使用pathPattern匹配模式

1
2
3
4
<data
android:pathPattern="/.*"
android:host="test"
android:scheme="app" />
1
.表示匹配任意字符 *表示匹配0次或多次  遗憾的是pathPattern无法使用标准的正则表达式 只有* 和.可用

关于sspPattern匹配模式

我们使用内链的格式一般和url格式一致,比如app://test, 如果我们想使用自定义格式比如这种app:test, 那常规的方法则不奏效,此时sspPattern就可以派上用场

我们在清单文件中如下配置即可:

1
2
3
<data
android:ssp="test"
android:scheme="app" />

同样该模式下对应三个属性:

  • ssp :字面值匹配模式(PATTERN_LITERAL) 内部采用equals函数
  • sspPrefix 前缀匹配模式(PATTERN_PREFIX) 内部采用startWith函数
  • sspPattern 全局匹配模式(PATTERN_GLOB) glob规则是一种简化的模式,只支持“*”和“.”作为通配符

实际上类似于url格式的内链, 比如app://test也可以使用ssp进行匹配:

1
2
3
<data
android:ssp="//test"
android:scheme="app" />

不过一般我们不会这么做, 因为直接使用host属性更加简洁

本文为作者原创 转载时请注明出处 谢谢

img

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

Mac平台下adb连接网易MuMu模拟器

发表于 2021-05-26

第三方模拟器adb无法自动识别, 每个模拟器都有各自的端口占用

在Mac平台下, 可以输入以下指令连接MuMu模拟器并调试

指令

1
adb connect 127.0.0.1:5555

WatchDog

网易模拟器自带应用崩溃日志收集功能, 可以快速定位crash原因, 针对一些第三方的App, 可以有效抓出异常

image-20220719122152894

本文为作者原创 转载时请注明出处 谢谢

img

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

Linux下查看目录和文件大小以及隐藏文件

发表于 2021-05-25

查看当前目录下的隐藏文件

1
ls -a

移动隐藏文件

1
mv xxx/.[^.]*

查看目录和文件大小

  1. 以字节形式显示

    1
    ls -ll
  2. 以KB MB等单位显示(推荐)

    1
    ls -lh
  3. 遍历当前目录下所有子目录大小

    1
    2
    3
    4
    5
    du -h 
    # 或指定层级遍历(*表示遍历所有子目录)
    du -h –max-depth=1 *
    # 或指定某个子目录下的层级
    du -h –max-depth=1 software/
  4. 只查看当前目录总大小

    1
    du -sh
  5. 查看当前目录下所有文件夹的大小

    1
    du -sh *
  6. 查看当前目录下除某些目录以外的所有文件夹大小

    1
    du -sh --exclude=dir1 --exclude=dir2 *

本文为作者原创 转载时请注明出处 谢谢

img

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

Mac上通过homebrew安装adb

发表于 2021-04-08

介绍

Mac安装adb,如果电脑上没有装android studio 那么最简单的办法是用homebrew

其中homebrew是macOS的一个包管理工具

步骤

1、安装homebrew

1
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

2、安装adb

1
brew cask install android-platform-tools

3、运行adb

1
adb devices

如果你有装Android Studio 那么可以参考以下步骤:

1. 安装IDE (android studio)

安装后,确认自己的adb目录,一般目录在 ~/Library/Android/sdk/platform-tools,~代表当前用户的根目录,如果不知道当前用户的根目录在终端上输入echo $HOME便可知晓。
最简单的方法,就是按快捷键command + shift + G ,然后把~/Library/Android/sdk/platform-tools这个目录复制到输入框内,按回车便可打开文件夹位置

2. 打开终端(应用程序——实用工具),运行:

1
sudo vi .bash_profile

屏幕上会提示你输入密码(输入密码的时候不会有任何字符显示,输完之后按回车就是了)
打开文件之后按i键进入插入模式(可理解为编辑模式),然后对该文件进行编辑

1
export PATH=${PATH}:你的platform-tools具体地址

我输入的是

1
export PATH=${PATH}:~/Library/Android/sdk/platform-tools

当然这是比较默认的情况,如果你改了Android的目录就要根据platform-tools这个文件夹的实际目录去填写。
编辑完成之后按 esc 键退出插入模式,之后按 :wq+ 回车保存退出,记得英文的冒号也是要输入的哦。

最关键的要输入生效命令

1
source ~/.bash_profile

之后在终端里试一下输入adb,如果显示出来是一大串文字而不是之前的 command not found就大功告成。

注意:

如果遇到关闭终端后再打开,又无法使用adb命令了,可以尝试以下办法
在~/.zshrc文件最后,增加一行:

1
source ~/.bash_profile

如果没有这个文件,可自己创建,运行命令touch .zshrc,运行命令open .zshrc打开编译。

3. 下面附上常用的adb命令

1
2
3
4
5
6
7
8
9
10
11
12
// 查看所有设备:
adb devices
// 安装指定apk(路径可不用手写,直接把apk文件拖拽过来):
adb install <file>
// 卸载指定包 :
adb uninstall <package>
// 拷贝文件到设备上:
adb push <local> <remote>
// 从设备中拷贝文件:
adb pull <remote> [<local>]
// 查看命令帮助:
adb help

本文为作者原创 转载时请注明出处 谢谢

img

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

wordpress批量修改文章状态的方法

发表于 2021-04-02

起因

手上有一个采集站点, 剩余3万的草稿, 原计划手动每日发布几十篇文章, 后来实在有些反人类, 干脆一次性全发布

如果使用wordpress自带的批量操作, 文章太多容易卡顿超时, 还是直接操作数据库来的快, 但是修改数据库存在一定风险, 因此建议提前做好备份

开始

  1. 第一步 备份数据库
1
mysqldump -uroot -p 数据库名 >数据库地址和名称

比如:

1
mysqldump -uroot -p wordpress>/logs/wordpress_bak.mql

回车后提示输入密码, 输入后即可备份

  1. 第二步 操作wordpress数据库

进入mysql内部

1
mysql -uroot -p 密码

查看所有数据库

1
show datebase;

选择指定数据库

1
use wordpress;

查看wordpress表

1
show tables;

查看wp-posts表字段

1
desc wp-posts;

最后修改wp-posts表中的post_status字段(关键)

1
UPDATE `wp_posts` SET `post_status` ='publish' WHERE (`post_status`='draft');

这里我是将所有的草稿改成已发布

wordpress中的文章状态有以下几种:

  • pending:待审
  • draft:草稿
  • auto-draft:自动保存的草稿
  • inherit:修订版本
  • trash:回收站
  • publish:已发布
  • future:定时
  • private:私有

如果你有其他需求, 比如想将所有待审的文章全部改成草稿, 那么只需修改相应的关键字就行,如:

1
UPDATE `wp_posts` SET `post_status` ='draft' WHERE (`post_status`='pending');

或者 你只想修改某一时间段内的文章, 那么可以加上时间条件,如:

1
UPDATE `wp_posts` SET `post_status` ='draft' WHERE `post_status`='pending' and `post_date` >='2020-05-01 00:00:00' and `post_date` < '2021-03-22 22:00:00:00';

本文为作者原创 转载时请注明出处 谢谢

img

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

Mac下 SSR无法正常使用Telegram问题及解决方法

发表于 2021-03-09

起因

最近在Mac上使用Telegram时,发现无法正常连接,无论是PAC还是全局均无效,在Google之后大多数答案都是Windows下的处理方法,并不适用。

Mac 配置了 ShadowsocksX-NG,开启后,浏览器可正常访问 Google,但是 Telegram 一直显示 Connection…

解决步骤如下:

选择 Proxy 为 Socks5 模式,服务器地址填 127.0.0.1 端口填 1080 (端口号需要查看你自己的)

下面我会用几张图来说明

1、在SSR的高级设置里查看Socks5端口号

img

2、设置Telegram代理 (共3步)

第1步

img

第2步

img

img

第3步

img

设置完后,发现代理前面有了一个勾,说明已经设置成功。

img

至此,就完成了所有设置,记得重启 Telegram,然后可以尽情在墙外漫游了

如果mac使用的socksx的客户端可能没有高级设置以查看地址及端口号。

此客户端一般是默认127.0.0.1,1080端口。

另外给大家分享一个免费的mtproxy分享网站:mtproto.cc

本文为作者原创 转载时请注明出处 谢谢

img

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

Could not resolve all dependencies for configuration app:debugRuntimeClasspath

发表于 2021-03-09

报错

1
2
3
Could not resolve all dependencies for configuration ':app:debugRuntimeClasspath'.
Could not create task ':app:minifyReleaseWithR8'.
Cannot query the value of this provider because it has no value available

同时提示:

1
2
3
Warning:<i><b>project ':app': Unable to build kotlin-kapt plugin configuration</b>
Details: org.gradle.api.internal.tasks.DefaultTaskContainer$TaskCreationException: Could not create task ':app:minifyReleaseWithR8'.
Caused by: org.gradle.api.internal.provider.MissingValueException: Cannot query the value of this provider because it has no value available.</i>

同事那边代码正常编译运行, 我这边把代码拉下来后报错, 很大可能性是Studio环境问题

百度试了很多方案均不奏效

最后在StackOverflow上找到了答案:

是SDK版本和buildToolsVersion不一致导致的

只需将buildToolsVersion版本改成本机已装SDK版本即可, 或者不改动代码 下载一个与之对应的SDK版本

问题解决

本文为作者原创 转载时请注明出处 谢谢

img

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

Git HEAD detached from XXX (git HEAD 游离) 解决办法

发表于 2021-03-08

起因

通常我们在首次进行代码的拉取的时候容易出现HEAD游离状态, 也就是说当前操作不在任何一个现有分支上, 一般情况下我们在进行代码修改时需要先将对分支进行相应切换, 比如在master分支上进行开发, 那就git checkout master切换到master分支

但是很多情况下我们容易忽视这个习惯, 导致代码提交时才发现处在游离分支上, 这个时候如果进行分支的强行切换意味着所做的代码修改全部付之一炬, 那我们该如何处理这种情况呢?

事实上, git已经给我们提供了相应的智能提示, 在我们push代码时会警告提示我们:

1
2
3
4
5
6
7
8
9
10
11
Warning: you are leaving 1 commit behind, not connected to
any of your branches:

84220ac update

If you want to keep it by creating a new branch, this may be a good time
to do so with:

git branch <new-branch-name> 84220ac

Switched to branch 'master'

这时我们只需要新开一个分支存储游离的内容, 然后再将两个分支进行合并即可

解决方案一

  1. 第一步 将游离部分代码放到一个临时分支

    1
    git branch temp 84220ac
  2. 第二步 切换到开发主分支

    1
    git checkout master
  3. 第三步 将临时分支代码合并到开发主分支

    1
    git merge temp
  4. 第四步 删除临时分支

    1
    git branch -d temp

解决方案二

本方案适用于代码还未commit

  1. 第一步 将游离代码放置到暂存区域

    1
    git stash
  2. 第二步 将暂存区域的代码pop出来到当前分支

    1
    git pop

本文为作者原创 转载时请注明出处 谢谢

img

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

Windows平台使用QEMU搭建ARM+Linux开发环境

发表于 2021-02-02

起因

由于目前市面上很多模拟器诸如夜神,网易MUMU,基本上使用的是x86的架构,虽然运行ARM程序没有问题,但是如果想使用gdb对ARM程序进行调试的话,就显得力不从心了,各种问题层出不穷,

当然调试x86程序是没有问题的,

如果非要对ARM程序进行gdb调试的话,可以采用Android Studio原生的模拟器(原生ARM太卡),但是考虑到很多人并不是从事安卓开发,加上Studio中的模拟器本就基于QEMU, 那么为了方便,我们直接搭建QEMU的环境

实验环境

  • Windows宿主平台

  • QEMU安装包(这里使用的是20201124的版本):https://qemu.weilnetz.de/w64/

  • 树莓派系统镜像:http://downloads.raspberrypi.org/raspbian/images/raspbian-2020-02-14/

    树莓派是基于Debian的Linux系统

操作步骤

QEMU下载安装完毕后,其安装目录会包含很多不同架构的执行文件,这里我们选择qemu-system-arm.exe,打开命令窗口:

1
qemu-system-arm.exe -machine versatilepb -L  -m 128  -hda 2020-02-13-raspbian-buster.img

相关指令选项介绍:

  • -M :指定机器
  • -name:给虚拟系统起个名称
  • -cpu:指定cpu型号
  • -smp :指定cpu的个数 比如-smp 2
  • -m: 指定内存大小单位MB
  • -vga :指定显卡 比如 -vga vmware
  • -hda: 指定硬盘镜像
  • -initrd: 指定 RAM磁盘镜像
  • -fda : 指定软盘镜像
  • -L:bios位置
  • -cdrom:光盘镜像
  • -no-reboot: 不重启退出
  • -kernel :指定内核文件
  • -serial :设置串口 比如:-serial stdio 表示 重定向Guest 的串口到Host的标准输入输出
  • -boot :启动模式 一共有三种 , 分别为floppy(a), hard disk(c), CD-ROM(d)

上面这条指令显然无法启动系统,因为还缺少了相应kernel-qemu文件和配置:

kernel-qemu下载:

GitHub - dhruvvyas90/qemu-rpi-kernel: Qemu kernel for emulating Rpi on QEMU

我们选择里面的versatile-pb-buster.dtb 和kernel-qemu-5.4.51-buster 这两个文件进行下载,这是和系统版本一一对应的。下载后最好放在qemu的安装目录

然后输入以下指令:

1
qemu-system-arm -M versatilepb -cpu arm1176 -m 256 -drive "file=系统镜像路径,if=none,index=0,media=disk,format=raw,id=disk0" -device "virtio-blk-pci,drive=disk0,disable-modern=on,disable-legacy=off" -net "user,hostfwd=tcp::5022-:22" -dtb versatile-pb-buster.dtb -kernel kernel-qemu-5.4.51-buster -append "root=/dev/vda2 panic=1" -no-reboot -net nic

注意:需要按照以上指令运行,否则有可能出现系统启动不起来的情况

-net nic 可开启网络 方便远程连接

-net "user,hostfwd=tcp::5022-:22" 表示设置端口映射

系统安装完毕后,直接进入树莓派桌面,在弹出的设置窗口中可以更改系统语言为中文, 还可以设置系统密码

至此ARM+Linux环境搭建完毕

准备开发

接下来我们通过ssh连接树莓派终端,打开cmd命令窗口,输入:

1
ssh pi@127.0.0.1 -p 5022

回车后会提示输入密码,这里输入之前设置的系统密码

此时就进入树莓派的Linux终端,为什么不直接使用qemu中的LX终端? 还不是因为模拟器延迟卡顿

如果想往树莓派中传输文件,可以直接使用ftp工具,比如FileZilla或者 SecureCRT 选择sftp或者ssh2模式,其登陆参数如下:

  • 主机:127.0.0.1
  • 用户名:pi
  • 端口:5022,
  • 密码同上

程序调试

紧接着使用gdb+gdbserver对C程序进行调试

首先利用ftp工具将已经编译好的可执行文件和GCC包下arm-none-linux-gnueabi\libc\usr\bin目录中的gdbserver传送到模拟器中

然后执行以下命令:

1
./gdbserver :22349 test

开始监听端口, 但是问题来了,该模拟器的ip不在局域网段上,导致宿主机连接不上, 如果你也出现同样的问题,可以采用端口映射的办法来替代,方法很简单,只需要在模拟器启动时多追加加上一行参数hostfwd=tcp::22349-:22349,具体启动指令修改如下:

1
qemu-system-arm -M versatilepb -cpu arm1176 -m 256 -drive "file=2020-02-13-raspbian-buster.img,if=none,index=0,media=disk,format=raw,id=disk0" -device "virtio-blk-pci,drive=disk0,disable-modern=on,disable-legacy=off" -net "user,hostfwd=tcp::5022-:22,hostfwd=tcp::22349-:22349" -dtb versatile-pb-buster.dtb -kernel kernel-qemu-5.4.51-buster -append "root=/dev/vda2 panic=1" -no-reboot  -net nic

如此一来就可以在宿主gdb调试窗口中直接使用以下指令进行连接:

1
(gdb) target remote 127.0.0.1:22349

连接成功了,通过以上这种方式,我们只需要将模拟器启动使其后台运行,我们通过ssh进行登录连接,这样速度快了很多,而且相比一些安卓模拟器,QEMU占用系统资源也不高

另外我们发现,还存在声卡缺失,同时运行有延迟卡顿现象,我们接下来对这两方面进行优化

小问题

如果是raw格式,可能会有些风险警告,可以通过-drive format=raw进行指定处理:

1
qemu-system-arm.exe  -machine raspi2b -drive file=2020-02-13-raspbian-buster.img,format=raw,index=0,media=disk

附加内容

查看cpu信息:

1
lscpu

查看系统和内核版本:

1
uname -a

镜像备份模式

随着我们对系统的频繁操作我们发现系统镜像文件在不断增大,此时想要回到原来的状态,只能重新下载镜像安装了,如果你不想遭受重新下载的痛苦,那么建议你使用备份镜像的模式进行系统的安装

这时qemu-img.exe派上了用场,它不仅可以帮助你创建空镜像文件,而且还可以对已有的镜像文件进行格式转换,QEMU支持的镜像有以下:

Image format Argument for -f and -O options
VMDK (VMware) vmdk
QCOW2 (KVM, Xen) qcow2
VHD (Hyper-V) vpc
VHDX (Hyper-V) vhdx
RAW raw
VDI (VirtualBox) vdi

qemu-img 支持非常多种的文件格式,可以通过 qemu-img -h 查看.
其中 raw 和 qcow2 是比较常用的两种,

raw 是 qemu-img 命令默认的,qcow2 是 qemu 目前推荐的镜像格式,是功能最多的格式

创建空镜像文件:

1
qemu-img create -f qcow2 test.qcow2 10G
  • -f 选项用于指定镜像的格式,

  • qcow2 格式是 QEMU最常用的镜像格式,采用来写时复制技术来优化性能。

  • test.qcow2 是镜像文件的名字,

  • 10G是镜像文件最大值

镜像转换:

1
qemu-img.exe  convert -f raw system.img -O vmdk  system.vmdk

表示将原始格式的镜像文件转换成vmdk格式

使用备份镜像的方式启动镜像示例:

1
qemu-system-x86_64 -m 2048 -enable-kvm test.qcow2 -cdrom Centos-Desktop-x86_64-20-1.iso

附加镜像

  • openwrt:https://archive.openwrt.org/chaos_calmer/

  • Debian系统镜像:https://people.debian.org/~aurel32/qemu/

  • 谷歌安卓原生镜像:https://developers.google.cn/android/images

  • 树莓派x86镜像: https://www.raspberrypi.org/downloads/raspberry-pi-desktop/

本文为作者原创 转载时请注明出处 谢谢

img

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

使用Clang编译C程序在安卓设备中执行

发表于 2021-02-01

由于Android NDK从r18开始就已经抛弃GCC,转而将Clang当作默认编译器,因此我们直接使用NDK工具包进行编译

实验环境

  • 安卓模拟器
  • android-ndk-r19c

实验步骤

第一步 源码编写

新建test.c文件

1
2
3
4
5
6
7
#include <stdio.h>  

int main()
{
printf("Hello world!\n");
return 0;
}

第二步 源码编译

在android-ndk-r19c目录下toolchains文件夹中的llvm文件夹即为clang编译工具包

在llvm的子目录bin下存放这针对各个架构的clang编译器,由于模拟器是ARM架构,这里我们使用armv7a-linux-androideabi23-clang

在命令窗口执行如下指令:

1
armv7a-linux-androideabi23-clang test.c -o test

由于clang已经指定了Android23版本的SDK,这里无需要像GCC那样指定-static编译

第三步 将编译后的可执行文件传至安卓设备

1
adb push test /data/

第四步 执行文件

直接在控制台输入文件名即可执行

1
./test

如果提示权限拒绝,那么

1
chmod 777 test

附加

如果C语言和汇编语言混合开发,同样也可使用clang编译:

1
armv7a-linux-androideabi23-clang aaa.s test.c -o test

本文为作者原创 转载时请注明出处 谢谢

img

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

1…242526…48

乱码三千

android程序员一枚,擅长java,kotlin,python,金融投资,欢迎交流~

479 日志
139 标签
RSS
© 2024 乱码三千
本站总访问量次
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4
0%