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

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


  • 首页

  • 归档

  • 搜索

关于Markdown图表绘制

发表于 2022-07-03

前言

写作时难免会有图表绘制需求 比如下面几种

示例

第一种样式时序图
1
2
3
4

Alice -> Bob:Hello Bob, How are you?
Note right of Bob: Bob thinks
Bob -> Alice: I am good thanks!
第二种样式时序图
 sequenceDiagram
    participant Alice
    participant Bob
    Alice->John: Hello John, how are you?
    loop Healthcheck
            John->John: Fight against hypochondria
    end
    Note right of John: Rational thoughts 
prevail... John-->Alice: Great! John->Bob: How about you? Bob-->John: Jolly good!
甘特图
  gantt
    dateFormat  YYYY-MM-DD
    title Adding GANTT diagram functionality to mermaid
    section A section
    Completed task            :done,    des1, 2014-01-06,2014-01-08
    Active task               :active,  des2, 2014-01-09, 3d
    Future task               :         des3, after des2, 5d
    Future task2               :         des4, after des3,6d
上下流程图
graph TD;
            A-->B;
            A-->C;
            B-->D;
            C-->D;
左右流程图
graph LR;

律动乐器-->律动+氛围乐器-->律动+鼓组贝斯-->律动+鼓组贝斯+氛围乐器;
铺底+氛围-->铺底+氛围+律动-->铺底+氛围+律动+鼓组贝斯-->追加间奏乐器;
自定义style的流程图
graph LR;
    id1(Start)-->id2(Stop)
    style id1 fill:#f9f,stroke:#333,stroke-width:4px
    style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
各种形状的流程图
graph  TD;
    A[/Christmas\]--> B[\This is the text in the box\]-->
     C[\Go shopping/]-->D[/This is the text in the box/]-->E{{This is the text in the box}}-->F{This is the text in the box}-->G>This is the text in the box]-->H((This is the text in the circle))-->J(This is the text in the box)

语法实现

时序图demo代码:

1
2
3
4
5
6
7
8
9
10
11
12
    <pre class="mermaid">    sequenceDiagram
participant Alice
participant Bob
Alice->John: Hello John, how are you?
loop Healthcheck
John->John: Fight against hypochondria
end
Note right of John: Rational thoughts <br/>prevail...
John-->Alice: Great!
John->Bob: How about you?
Bob-->John: Jolly good!</pre>
**甘特图demo代码:**
<pre class="mermaid">    gantt
dateFormat  YYYY-MM-DD
title Adding GANTT diagram functionality to mermaid
section A section
Completed task            :done,    des1, 2014-01-06,2014-01-08
Active task               :active,  des2, 2014-01-09, 3d
Future task               :         des3, after des2, 5d
Future task2               :         des4, after des3, 5d
section Critical tasks
Completed task in the critical line :crit, done, 2014-01-06,24h
Implement parser and jison          :crit, done, after des1, 2d
Create tests for parser             :crit, active, 3d
Future task in critical line        :crit, 5d
Create tests for renderer           :2d
Add to mermaid                      :1d</pre>

流程图demo代码:

    <pre class="mermaid">    graph TD;
            A-->B;
            A-->C;
            B-->D;
            C-->D;</pre>

### 总结

以上只是列举其中几种 , 除此之外还可以绘制饼状图 状态图 类图 需求图等等

更多技巧可以参考`mermaid`文档: 《[mermaid官方文档](https://mermaid-js.github.io/mermaid/#/flowchart)》





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

![](https://gitee.com/songjianzaina/SavePicGoPic/raw/master/img/20191119095516.png)

*[乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站](https://code.newban.cn/)*

关于Git查看提交修改的文件列表

发表于 2022-06-28

1.查看最后一次提交记录的修改文件信息

1
git show --raw

2.查看指定commit id对应修改文件列表

1
git show --raw commit_id
1
git show --raw 2f80f1c8bb2cb8e91d22ad38480b681c194f6518

3.查看所有提交记录的修改文件信息

1
git log --stat
1
git log --name-only

4.查看所有修改相关的commit ID和comment信息

1
git log --pretty=oneline

5.查询指定author的修改信息

1
git log --author=jack.li

6.查看指定author在指定时间修改信息

1
2
3
4
5
6
7
8
$ git log --pretty="%h - %s" --author='Junio C Hamano' --since="2008-10-01" \
--before="2008-11-01" --no-merges -- t/
5610e3b - Fix testcase failure when extended attributes are in use
acd3b9e - Enhance hold_lock_file_for_{update,append}() API
f563754 - demonstrate breakage of detached checkout with symbolic link HEAD
d1a43f2 - reset --hard/read-tree --reset -u: remove unmerged new paths
51a94af - Fix "checkout --track -b newbranch" on detached HEAD
b0ad11e - pull: allow "git pull origin $something:$current_branch" into an unborn branch

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

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

从found.000中恢复数据 某个文件夹突然不见了

发表于 2022-06-03

说明

  • 本文是问题解决后编写的,解决顺序已经尽力按照我记得的编写。希望能给遇到此问题的朋友一份参考。
  • 因涉及数据此等重要性的东西,建议还是看完全文再操作。在理解了我的解决思路之后,并且觉得我的方案有用方可尝试。切勿在你解决无望的时候,看到本文以为是发现新大陆,然后盲目操作导致数据丢失得不偿失!(因为我搜索过关于found.000的相关,有些人说用数据恢复软件,有些人说这个文件恢复不了,还有人提问该文件夹能不能删除诸如此类)
  • 但是你还是想尝试,可以尝试复制一份found.000出来,在别的盘上或者电脑上对该文件夹进行操作。(切勿在源路径操作,方便你实在不行的情况下拿去维修)或者你对自己非常有信心,就在源路径下操作吧(因为我也不知道复制出来能不能恢复😂)。
  • 本文更多的是提供思路,实际操作需要的一些诸如命令行操作,文件夹提权等需要大家自行百度。

    问题说明(此时我的电脑上是没有found.000这个文件的)

    某天我的D盘下的“资料”文件夹突然不见了。
    当时我的思路是:
  1. 该文件夹被病毒隐藏了?

  2. 我之前误删了?

初步解决方案

通过问题排查(查看隐藏文件+受保护的文件),发现思路1是错误的。

那接下来就是怎么验证误删?因为该文件夹比较大,删除的情况下会提示放入不了回收站,要直接删除吗?所以回收站没有我的删除记录。然后思路2的解决方法是进PE使用数据恢复软件(如:Recuva,金山数据恢复)查看有没有相关痕迹,结果发现没有“资料“文件夹被删除的相关痕迹(着急解决问题,没想到截图)。(进不进PE没多大关系,但可能是因为我进PE恢复数据导致重启电脑的时候进行磁盘检查,然后我的电脑上才有found.000)

经过以上的方案,还是不行之后。我剩下的思路只有装杀软看看。但是,我没有装,因为接下来的操作我也是第一次遇到。

无意中,我使用 everything 软件进行搜索”资料”的时候,通过搜索结果看到我的文件还是存在的。忘记截图了,但我记得结果是xxx资料 D:\资料\xxx。当时我看到我的文件夹存在的时候很开心,马上右键打开所在路径,结果提示:请检查你的路径,没有该路径之类的话。(当时我一脸懵圈。everything可以搜索到,难道是everything之前的索引还存在?这个结果只是一个假象?)

  • everything的结果说明了什么?(我此时相信我的文件夹还是存在的)说明了我的文件夹还是存在的。没有被数据恢复软件没有检索到是因为我的文件夹根本没有被删除啊。但是不知道为什么就是看不到它了(注意,此时并不是隐藏,因为常规的查看隐藏文件方式已经不起作用了,我的理解是,因为某个原因,系统对”资料“这个文件夹的索引没有了)

    可行的解决方案

  • step1: 确保你的硬盘里有found.000*
    因为我成功解决问题的基础是有这个文件。所以只需要在重启的时候进行磁盘检查,让系统重新找回对这个文件夹的索引。(如果你的电脑此时有这个文件跳过这一步)

step2: 存在 found.000后
使用everything 搜索一下丢失文件夹的关键字。如下:可以看到我的资料都在这个文件夹下。

在这里插入图片描述

step3: 进入文件夹

于是我马上右键打开所在路径,我的天!进来了。我试了一下打开 pdf ,是可以打开的。我马上复制一份到别的盘打开,是可以打开的!于是我慢慢一步一步点上一级路径跳转,是可以访问的。可是当我点击dir0001.chk之后提示错误了。(具体提示的错误我忘记了)

在这里插入图片描述

step4: 从文件浏览器进入found.000

因为step3: 倒着进不了上一级路径。此时我想能不能正着进入该路径,于是我从文件夹点进去,提示权限不足,此时对文件夹提权就好了。

在这里插入图片描述

进入后,发现如下:(写下此文的时候我已经忘记相关弹窗提示,但是我记得我第一次提权进入该文件夹的时候没有这么多东西的,我是进行了step5才看到下图如此完整的文件夹)

在这里插入图片描述

step5: 从bash进入dir0001.chk

在step4我说明了我第一次进入found.000文件夹是没有什么东西的。于是我的思路是:无论如何都要进入单片机的上一级目录(我原本保存的路径就是D:\资料\单片机),所以虽然不能进入found.000,但是只要我进入”单片机“上一级目录就可以对我之前的数据全部复制保存。

  • 怎么操作?很简单,当时我想到的是从命令行看能不能进入,于是有下图:

    在这里插入图片描述

奇怪的是,我从命令行进入单片机的上一级目录之后,我就可以正着进found.000文件夹,并且还能看到比较多的文件夹了。才有了step4的第二张截图。然后也有了下面的截图。

在这里插入图片描述

经过我的发现,之前的数据并不是全都在dir0001.chk中,在found000文件下的其他dirxxxx.chk都保存了我之前的资料。大家不放心每个文件夹都点开看看吧!

总结

  1. 想办法让电脑中存在 found.000(通过重启后进行磁盘检查)
  2. 想办法进入found.000(通过命令行,必要时结合 everything)
  3. 事后我想,是不是一开始就可以通过 命令行 进入该文件夹了?即使不能正着进去,我也可以通过 everything 打开所在路径之后再通过命令行进入,然后通过cp命令直接复制到别的盘保存。
  4. 同时,我成功恢复数据感觉也是很多的机缘巧合,比如,如果我不进PE恢复数据,是不是就没有磁盘检查了,也就没有生成found.000,我可能就还不能解决此问题了!

本文转载自: https://blog.csdn.net/u011897411/article/details/106879852

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

记录关于移动硬盘文件丢失的找回过程

发表于 2022-06-01

起因

由于居家办公需要, 经常使用移动硬盘来回在公司和宿舍之间进行大文件拷贝, 某一天突然发现硬盘中的文件夹消失不见, 而空间占用依然存在

难道是文件被隐藏了? 检查一番之后发现不是

当时我就慌了 因为消失的都是重要文件, 于是赶紧百度

搜索一阵之后, 我推测可能是不同系统兼容性错误导致的磁盘坏道

因为公司的电脑是Mac系统 宿舍的电脑是Windows系统, 而我的硬盘格式是NTFS, Mac本身是不兼容该格式的, 加上我使用了Omi NTFS这个工具进行桥接中转 硬盘出现点问题 似乎是情理之中

既然发现了问题所在, 那就需要解决 尽可能地将文件恢复回来

而我第一时间想到的便是进行磁盘修复, 当我在Windows平台中对硬盘进行修复之后, 丢失的文件夹确实出现了 但是却变成了一个未知文件 无法打开

这就有点坑了

无奈之下我停止了对该硬盘进行文件写入操作, 免得操作频繁导致后期无法恢复

于是将该硬盘放置了一段时间, 直到有一天我需要从硬盘中未被破坏的文件夹里面找寻一些资料, 顺带使用了everything软件检索, 突然获得了意外惊喜, everything检索到了丢失文件夹中的资料

这意味着文件依然存在于移动硬盘中, 可能是被迁移到了某个隐藏文件中

我利用everything找到了丢失文件所在目录, 名为found.000

这个found.000目录是隐藏目录, 即便开启显示隐藏文件夹功能也是看不到的, 而且这个目录需要管理员权限才能对里面的文件进行拷贝移动操作

既然目录找到了 那么恢复文件就不难了

操作步骤

  1. 打开管理员cmd窗口, 进入到found.000目录

    1
    F:    //进入移动硬盘盘符
    1
    cd found.000   //打开隐藏文件
  2. 列出当前目录下所有文件夹和文件(包含隐藏文件夹)

    1
    dir /A *
  3. 移动文件

    1
    move 需要移动的文件或文件夹名 目标文件夹名

被恢复的目录中可能会存在一些隐藏目录, 为了确保所有文件都恢复, 需要仔细检查

网上有位小伙伴也碰到了和我类似的问题, 大家有兴趣的可以参考一番:

《【问题记录】从found.000中恢复数据(某个文件夹突然不见了)》

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

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

Windows平台下cmd常用命令

发表于 2022-05-29

常用命令如下

  1. 进入某个盘符

    1
    盘符名:
  2. 打开文件夹

    1
    cd 文件夹名
  3. 回退到上一层目录

    1
    cd ..
  4. 进入根目录

    1
    cd\
  5. 列出当前目录下所有文件夹(不含隐藏文件夹)

    1
    dir
  6. 列出当前目录下所有文件夹(包含隐藏文件夹)

    1
    dir  /A:H
  7. 列出当前目录下所有文件夹和文件(包含隐藏文件夹)

    1
    dir /A *
  8. 移动文件

    1
    move 需要移动的文件或文件夹名 目标文件夹名
  9. 拷贝当前目录下所有文件到D盘

    1
    copy * "d:\"
  10. 更改文件属性

    1
    2
    3
    4
    5
    6
    7
    8
    attrib 文件名 -H 
    attrib 文件名 +H
    attrib 文件名 -A
    attrib 文件名 +A
    attrib 文件名 -R
    attrib 文件名 +R
    attrib 文件名 -S
    attrib 文件名 +S

    注释:

    • H: 表示隐藏属性
    • A: 表示存档属性
    • R: 表示只读属性
    • S: 表示系统属性

    加号表示添加 减号表示移除

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

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

Window10如何设置只允许某个程序联网

发表于 2022-05-28

起因

最近由于疫情原因不得不远程办公 宿舍有台笔记本 用于连接公司的电脑 由于平常在宿舍不怎么用电脑上网 所以没有装宽带 索性使用手机热点

考虑到居家办公时长的不确定性 在使用热点上网之前 我打开了win10自带的流量计费功能

这个功能可以限制系统后台程序偷跑流量 从而达到节省流量的目的

毕竟 流量不便宜

我已经做好了打持久战的准备

当我愉快的玩耍一会儿后 闲暇之余看了一下流量消耗 差点没让我喷血

这虚幻居然给我偷跑流量 我明明没有启动这个应用啊 都不知道啥时候跑起来的 想想我远程软件也才用了几十兆流量而已 顿时气不打一处来

看来这个流量计费功能也不太好使呀 第三方应用它管不了

于是我开始想 能不能只让我这个TeamView联网 而其他应用的禁止联网呢? 为了解决这个问题 我特地百度了一番 经过亲自尝试 最后得出了以下方案:

使用防火墙功能 阻止所有应用程序联网 然后对需要联网的应用开白名单即可

具体步骤如下:

操作步骤

第一步 开启防火墙功能

这里 我将专用网络防火墙打开 并且将热点改成专用网络

第二步 阻止所有应用联网

我们进入防火墙高级设置页面:

然后进入属性设置, 将专用配置文件选项下的出站连接改为阻止:

这样就实现了阻止所有应用联网的目的

第三步 对需要联网的应用单独开启白名单

新建一个出站规则 选择相应的应用程序 并允许联网:

点击完成

此时TeamView可以联网了 而其他的应用则不能联网

接下来 可以放心大胆的连上热点了 不用担心流量偷跑的问题

总结

是教训 也是经验

当我写完这篇文章时 我的气也基本消了 因为我又收获了一个小经验 没有什么比这个更让我满足的了

希望这个经验能帮助到你

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

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

说说移动设备的各种标识码(DeviceID, IMEI, UUID, UDID, OAID, IDFA, GAID

发表于 2022-04-25

名词解释

  • Device ID:设备ID。

  • IMEI:(International Mobile Equipment Identity)国际移动设备标识的缩写。是由15位数字组成的“电子串号”,它与每台手机一一对应,每个IMEI在世界上都是唯一的。

  • MEID:(Mobile Equipment Identifier) 移动设备识别码是CDMA手机的身份识别码,也是每台CDMA手机或通讯平板唯一的识别码。

  • IDFA:(Identifier For Advertising)iOS独有的广告标识符。

  • UDID:(Unique Device Identifier)唯一设备标识码。

  • UUID:(Universally Unique Identifier)通用唯一识别码。目前最广泛应用的UUID,是微软公司的全局唯一标识符GUID。其目的是让分布式系统中的所有元素,都能有唯一的辨识信息,而不需要通过中央控制端来做辨识信息的指定。

  • OAID:(Open Anonymous Device Identifier) 开放匿名设备标识符。

  • GAID:Google Advertising ID。

详细介绍

(1)Device ID

设备ID,具有唯一性。其中又包括IMEI 和 MEID/ESN。一般情况我们获取手机的DeviceId也就是手机的IMEI码。

(2)IMEI

GSM设备返回的,并且是写在主板上的,重装APP不会改变IMEI。

Android:Android 6.0以上系统需要用户授予read_phone_state权限(弹窗授权),如果用户拒绝就无法获得。但是Andorid Q(10.0)版本,将无法获取IMEI,出于用户隐私等一系列安全问题的考虑。将用其他匿名标识符代替,比如OAID。

IOS:iOS 5 之后被禁止。

IMEI是联通、移动手机的标识,MEID是电信手机的标识。

IMEI可以在在移动设备上查询到,一般来说一个双卡手机不止一个IMEI值,全网通双卡手机有两个IMEI和一个MEID。

(3)MEID

在手机键盘直接键入*#06#可获得。

MEID/ESN:CDMA设备返回的,一般不使用。

(4)mac地址

硬件标识符,包括WiFi mac地址和蓝牙mac地址。

Android:Android 6.0之后被禁止,若获取则会被判定为有害应用。

IOS:iOS 7 之后被禁止(同时禁止的还有OpenUDID)。

(5)UDID

用来标示设备的唯一性,由40个字符的字母和数字组成 。

Android:获取UUID后,写入.so文件生成UDID。即使APP重装,值也不变,除非root手机(普通用户做不到)。

IOS:iOS 6 之后被禁止获取系统原生的UDID,但可以通过uuid,写入到钥匙串中,从而获得自定义的UDID(非系统原生),即使用户重装APP,只要每次都取这个钥匙串返回,就是不变的。

OpenUDID:是一个替代 UDID 的第三发解决方案。缺点是如果你完全删除全部带有 OpenUDID SDK 包的 App(比如恢复系统等),那么 OpenUDID 会重新生成,而且和之前的值会不同,相当于新设备。

(6)UUID

APP重装后会改变。

(7)IDFA

IDFA 是苹果 iOS 6 开始新增的广告标识符,用于给开发者跟踪广告效果用的,可以简单理解为 iPhone 的设备临时身份证,说是临时身份证是因为它允许用户更换,IDFA 存储在用户 iOS 系统上,同一设备上的应用获取到的 IDFA 是相同的。iOS 用户可以通过(设置程序 -> 通用 -> 还原 -> 还原位置与隐私)更换 IDFA,iOS 10 系统开始提供禁止广告跟踪功能,用户勾选这个功能后,应用程序将无法读取到设备的 IDFA。(在统计唯一用户的时候,IDFA 的可变性会造成部分用户的重复统计。)

适用于对外:例如广告推广,换量等跨应用的用户追踪等。

总结:iOS 6 时面世,可以监控广告效果,同时保证用户设备不被APP追踪的折中方案。可能发生变化,如系统重置、在设置里还原广告标识符。用户可以在设置里打开“限制广告跟踪”。

(8)OAID

APP类广告效果追踪需要使用到用户的设备标识进行广告点击和转化效果的匹配,而安卓系统当前强依赖于IMEI的获取,上面提到Andorid Q(10.0)版本后,将无法获取IMEI。基于此背景,进行广告投放的效果追踪,需要能够替代及补充IMEI的设备标识。

目前OAID作为目前市场主流的归因补充标识,OAID是由中国信息通讯研究院号召,移动安全联盟推行的安卓设备标识,在无法获取设备号情况下可以使用该标识进行数据匹配,目前主流厂商均已在新版本系统中支持该标识的获取,具有权威性。OAID可以理解为是国内联合推出的广告标识。

与IDFA类似,对于OAID 用户也可以手动在设置中通过重置广告标识符更换OAID或者“限制广告跟踪”。

与OAID相关的设备标识体系中拥有四种设备标识:

(9)GAID

Google推出的广告标识,与IDFA类似。在装了google play service的安卓手机上,才可以获取到GAID。

广告id是用户特殊的,独特的,可重置的广告id,由Google Play Service 提供,它为用户更好的控制,为开发人员提供简单、标准的系统继续使用你的应用程序,它用于广告目的的匿名标示符和或者重置其标示符或者退出以利益为基础的Google Play的应用程序。

主要用于广告定向,并且和IDFA一样 对于GAID 用户也可以自己设置禁止广告跟踪。

整理,借鉴了多个地方的资料,有不准确的欢迎指出!

用户唯一标识

为什么要建设用户唯一标识

如何区分某个用户就是他这个用户,而不是另一个用户,在数据埋点中,是一个非常重要的事情。因为如果做不到用户的唯一识别,那凡是涉及到用户的数据都将是错的(比如用户量、新增用户数、活跃用户数等等)。所以建设用户唯一标识,尤为重要。

基本概念

设计埋点字段的时候,有两个字段是一定要包括的,即设备ID和用户ID。这两个字段应该纳入通用字段,每个埋点的事件都必须要集成收集。

(1)设备ID

使用相应的算法,生成一个设备ID,以唯一识别用户的终端设备。不同终端的设备ID,其生成算法规则不一样,以下列举不同终端的设备ID的生成规则:

AndroidApp

安卓系统历经多次升级,对权限控制越来越严格,唯一识别手机的方法也在发生变化。下面整理一下安卓系统适合做设备唯一标识符的几个标识符,以及其特性:

img

从表格中看出,IMEI是最适合做设备唯一标识的,奈何获取IMEI需要授予权限且Android 10以后不再开放IMEI的权限。综合起来,安卓系统中,应该按照IMEI ->OAID -> ANDROID_ID的顺序生成设备ID。即先获取IMEI号,获取不到IMEI时获取OAID,获取不到OAID时,再获取ANDROID_ID,然后使用相关算法生成设备ID。

IOS App

苹果系统,可用于识别唯一设备的标识不多,如下图。综合起来,苹果系统生成设备ID的标识符顺序应该是IDFA -> IDFV ->UDID,即先获取IDFA,获取不到在获取IDFV,获取不到IDFV时,再获取UDID,然后使用相关算法生成一个设备ID。

img

Web网站

Web网站,使用cookie_id作为设备ID,并存储在浏览器的cookie中。

微信小程序

通常做法使用openid作为设备ID,当然也可以自己生产一个ID,作为设备ID。如果用过openid作为设备ID,需要注意微信小程序的冷启动问题(获取 openid 是一个异步的操作,所以会导致数据上报的时候,可能还没获取到openid,这就是导致设备ID为空)。

2)用户ID

用户ID,即用户在业务产品注册的用户账号。

收集到设备ID和用户ID后,就要想办法将设备ID和用户ID关联起来,也即用户唯一标识建模,详见下文。

用户唯一标识建设

设计一个字段,比如就叫distinct_id(设备ID命名为device_id,用户ID命名为user_id)这个字段用于识别唯一用户。凡是统计用户相关的数据时,都以distinct_id作为用户的唯一区别标识。下面,以具体案例进行阐述。

img

步骤说明:

  1. 小明在一部手机上启动了app。该手机的device_id为x1,此时生成一个dsitinct_id为d1;
  2. 小明在这个手机上用账号u1进行登录。此时device_id为x1,user_id为u1,dsitinct_id为d1;
  3. 小明继续在这手机上使用app。此时device_id为x1,user_id为u1,dsitinct_id为d1;
  4. 小明退出自己的账号,继续使用app。此时仍然device_id为x1,user_id为u1,dsitinct_id为d1;
  5. 小明把手机给了小花,小花用自己的账号u2登录app。此时u2去关联x1,因为x1已经与u1关联,故关联失败。所以重新生成一个distinct_id为d2来标识此用户(u2);
  6. 小花继续使用app。此时device_id为x1,user_id为u2,dsitinct_id为d2;
  7. 小明换了部新手机,使用app。此时device_id为一个新的x2,后台生成一个新的dsitinct_id为d3;
  8. 小明在新手机上,使用账号u1登录了app。此时u1去关联x2,因为x2之前没有与账号关联过,所以关联成功,但是u1已经有一个dsitinct_id为d1,所以此时的dsitinct_id仍然为d1;
  9. 小明继续在新手机上使用app。此时device_id为x2,user_id为u1,dsitinct_id为d1。

此时三个字段的映射关系为:

img

(1)后续修复

事件字段修复

小明换新手机后,在登录前,系统给分配的dsitinct_id为d3,不符合实际情况,故要将在新手机上登录前的dsitinct_id修复为d1。如下:

img

映射表修复

1)删除d3与x2的映射关系

2)将x2添加到d1的device_id_list字段

img

本文转载自: https://zhuanlan.zhihu.com/p/395387972

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

PC端快速下载视频网站的视频

发表于 2022-04-20

前言

有时候在逛B站或者看QQ音乐MV的时候 有把视频下载到本地的需求

网上有很多针对特定网站视频的解析工具, 比如针对B站的有:

  • B站视频在线解析

  • Downkyi下载姬

  • 唧唧下载器

对于我这种只是偶尔下载个视频的懒人而言, 为了下载一个视频单独安装一个软件, 实在是不太能接受 自然是优先选择在线解析的方案

但是 大部分在线解析网站都是针对某一个或者某几个主流的视频网站进行解析处理, 如果碰上冷门网站 那就有些尴尬了

今天给大家介绍一个非常简单实用, 并且对所有视频网站都通用的一个方法, 只需要一个浏览器就能快速获取视频源地址

原料准备

  • 浏览器 (本文以谷歌浏览器为例)
  • 电脑

开始抓取

  1. 第一步打开浏览器 将视频地址填入地址栏

  2. 按F12进入开发者选项 选择移动设备浏览模式 对Media进行过滤 然后F5刷新页面

    image-20220424112429767

  3. 拷贝视频文件路径 直接浏览器下载或者第三方软件下载

    image-20220424112609595

博主对B站和QQ音乐进行了测试, 均能获取到原视频地址, 如果没有出现地址, 建议多刷新几次试试, 一般都没有问题

很多在线视频解析的原理也就是这么一回事

总结

上面这种方法 相信有很多人都知道, 但如果你不是做技术的, 可能就不太清楚了, 希望本文能帮到大家

另外 如果你有批量下载视频的需求, 该方法就有些费劲了, 这种情况建议大家使用软件进行解析下载

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

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

Android腾讯IM快速集成流程和注意事项

发表于 2022-04-01

前言

最近项目集成了及时通信业务, 采用的是腾讯IM

首先是SDK的快速集成, 步骤如下:

第一步 安装依赖包

1
implementation 'com.tencent.imsdk:imsdk-plus:5.6.1200'

第二步 初始化SDK (需要用到appid)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
V2TIMManager.getInstance()
.initSDK(this, "这里填写appid", V2TIMSDKConfig().apply {
logLevel = V2TIMSDKConfig.V2TIM_LOG_INFO


}, object : V2TIMSDKListener() {
override fun onConnecting() {
Log.i("KIM", "正在连接到腾讯云服务器")
}

override fun onConnectSuccess() {
Log.i("KIM", "已经成功连接到腾讯云服务器")

}

override fun onConnectFailed(code: Int, error: String?) {
Log.i("KIM", "连接腾讯云服务器失败 $code $error")
}
})

第三步 登录IM

1
2
3
4
5
6
7
8
9
10
11
12
V2TIMManager.getInstance().login(
"这里填当前用户id",
"这里填登录密钥 从后台获取",object : V2TIMCallback {
override fun onSuccess() {
Log.i(TAG, "登录成功")

}

override fun onError(code: Int, desc: String?) {
Log.i(TAG, "登录失败 $code $desc")
}
})

第四步 加入群聊房间 (如果是单聊可以跳过该步骤)

1
2
3
4
5
6
7
8
9
10
V2TIMManager.getInstance().joinGroup("这里填房间号 从后台获取", "", object : V2TIMCallback {
override fun onSuccess() {
Log.i(TAG, "加入群组成功")

}

override fun onError(code: Int, desc: String?) {
Log.i(TAG, "加入群组失败 $code $desc")
}
})

第五步 接收消息

如果业务不涉及音视频传输:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
V2TIMManager.getInstance().addSimpleMsgListener(object :
V2TIMSimpleMsgListener() {

// 对应 sendGroupCustomMessage
override fun onRecvGroupCustomMessage(
msgID: String?,
groupID: String?,
sender: V2TIMGroupMemberInfo?,
customData: ByteArray?
) {
super.onRecvGroupCustomMessage(msgID, groupID, sender, customData)
Log.i(TAG, "接收群聊自定义消息")
}

// 对应 sendGroupTextMessage
override fun onRecvGroupTextMessage(
msgID: String?,
groupID: String?,
sender: V2TIMGroupMemberInfo?,
body: String?
) {

Log.i(TAG, "接收群聊文本消息 $body")

}
override fun onRecvC2CTextMessage(msgID: String?, sender: V2TIMUserInfo?, text: String?) {
super.onRecvC2CTextMessage(msgID, sender, text)
Log.i(TAG, "接收单聊文本消息 $text")
}

override fun onRecvC2CCustomMessage(
msgID: String?,
sender: V2TIMUserInfo?,
customData: ByteArray?
) {
super.onRecvC2CCustomMessage(msgID, sender, customData)
Log.i(TAG, "接收单聊自定义消息 ")
}


})

如果业务涉及音视频传输:

1
2
3
4
5
6
V2TIMManager.getMessageManager().addAdvancedMsgListener( object : V2TIMAdvancedMsgListener() {
override fun onRecvNewMessage(msg: V2TIMMessage?) {
Log.i(TAG, "收到消息类型${msg?.elemType} ")

}
})

第六步 发送消息

如果业务不涉及音视频传输:

  1. 单聊 (分为文本消息和自定义消息)

    • 文本消息

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      V2TIMManager.getInstance().sendC2CTextMessage("这里填需要发送的文本",
      "这里填对方的登录id",
      V2TIM_PRIORITY_HIGH,
      object : V2TIMValueCallback<V2TIMMessage> {
      override fun onSuccess(t: V2TIMMessage?) {
      Log.i(TAG, "发送单聊文本消息成功")
      }

      override fun onError(code: Int, desc: String?) {
      Log.i(TAG, "发送单聊文本消息失败 $code $desc")
      }
      })
    • 自定义消息

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      V2TIMManager.getInstance().sendC2CCustomMessage("这里填需要发送的自定义消息 格式为字节数组",
      "这里填对方的登录id",
      V2TIM_PRIORITY_HIGH,
      object : V2TIMValueCallback<V2TIMMessage> {
      override fun onSuccess(t: V2TIMMessage?) {
      Log.i(TAG, "发送单聊自定义消息成功")
      }

      override fun onError(code: Int, desc: String?) {
      Log.i(TAG, "发送单聊自定义消息失败 $code $desc")
      }
      })
  1. 群聊 (分为文本消息和自定义消息)

    • 文本消息

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      V2TIMManager.getInstance().sendGroupTextMessage("这里填需要发送的文本",
      "这里填群聊房间id",
      V2TIM_PRIORITY_HIGH,
      object : V2TIMValueCallback<V2TIMMessage> {
      override fun onSuccess(t: V2TIMMessage?) {
      Log.i(TAG, "发送群文本消息成功")
      }

      override fun onError(code: Int, desc: String?) {
      Log.i(TAG, "发送群文本消息失败 $code $desc")
      }
      })
  • 自定义消息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    V2TIMManager.getInstance().sendGroupCustomMessage("这里填需要发送的自定义消息 格式为字节数组",
    "这里填群聊房间id",
    V2TIM_PRIORITY_HIGH,
    object : V2TIMValueCallback<V2TIMMessage> {
    override fun onSuccess(t: V2TIMMessage?) {
    Log.i(TAG, "发送群自定义消息成功")
    }

    override fun onError(code: Int, desc: String?) {
    Log.i(TAG, "发送群自定义消息失败 $code $desc")
    }
    })

如果业务涉及音视频传输:

该方法支持音视频图片 文本和自定义消息

1
V2TIMManager.getMessageManager().sendMessage()

注意事项

这里的坑主要在于消息的收发, 官方给的API比较多, 单聊和群聊串在一块, 看文档有时容易懵, 这里对收发消息的使用做了一个总结, 如下:

1
2
3
4
5
* IM群聊和单聊的消息收发走的是同一套  总共分为两种需求:
* 第一种: 不涉及音视频 只涉及字符串传输 那么监听消息使用addSimpleMsgListener 发消息使用sendC2C(Group)TextMessage和sendC2C(Group)CustomMessage
* 第二种: 涉及音视频等复杂消息传递 那么监听消息使用addAdvancedMsgListener 发消息使用V2TIMManager.getMessageManager().sendMessage()
*
* 注意: setGroupListener不是监听的群聊消息 而是对群组相关的事件监听 比如群创建通知 公告等等

附加

腾讯IM集成文档

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

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

Android集成支付宝支付以及沙箱环境测试注意事项

发表于 2022-03-01

前言

现在很多App都涉及到支付, 毕竟开发APP目的是为了盈利嘛, 通常我们会在App中同时集成支付宝和微信支付, 方便用户消费

集成相关

支付宝的集成相对简单, 前端无需添加APPID和密钥, 签名部分在在后端完成,只要确保应用签名和开发平台填入的保持一致就行, 不像微信不仅要配置APPID, 还要添加WXEntryActivity ,此外包名也必须匹配 少一个都不行

当然两者都需要在开发平台填入一个应用签名, 格式为MD5

沙箱环境

当我们SDK集成完毕, 后台接口也调好后, 开始测试支付, 那么问题来了, 支付可是得花钱的呀, 为了解决这个问题, 支付宝官方给我们提供了一个沙箱环境的支付宝, 方便开发测试

简而言之就是提供了一个测试用的支付宝账号, 里面有很多钱, 可以随便花, 哈哈, 不过仅限于测试

这个测试账号不能直接登录我们平常用的支付宝App, 需要下载一个沙箱用的支付宝App

这里提供了沙箱支付宝App下载地址

沙箱支付宝App下载

沙箱测试

安装完毕后登录沙箱账号, 看看你的应用能否调起支付

此时你会发现支付宝调不起来 ,如果返回错误码4000, 那么就是没有检测到沙箱支付宝App

此时 需要在支付Activity中开启沙箱环境, 代码如下:

1
2
3
4
5
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX)

}

如果依然无效, 那么大概率是后台签名出了问题, 后台网关需要改成沙箱环境地址

支付宝H5支付

当用户手机上未安装支付宝app时也需要支持支付功能的话, 可以采用H5页面支付方案, 此时需要在清单文件中声明相应Activity,如下:

1
2
3
4
5
6
7
8
9
<!--        支付宝客户端未安装时使用H5页面  -->
<activity
android:name="com.alipay.sdk.app.H5PayActivity"
android:exported="true"
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
<activity
android:name="com.alipay.sdk.app.H5AuthActivity"
android:exported="true"
android:theme="@android:style/Theme.Translucent.NoTitleBar" />

该功能可选, 如果不需要可不添加

总结

支付宝集成归纳如下:

  • 前端无需配置APPID, 只需确保应用签名正确 包名不一样也能正常调起
  • 沙箱测试, 前端需要使用EnvUtils开启沙箱环境
  • 沙箱支付宝登录使用开发后台提供的买家账号登录, 用于支付

微信支付集成归纳如下:

  • 前端需要配置APPID和密钥 同时包名和应用签名需要正确

  • 还需要再创建一个WXEntryActivity, 并在清单文件中注册

    清单文件中可以考虑使用activity-alias 实现多合一注册, 示例如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
      <activity-alias
    android:name="${applicationId}.wxapi.WXPayEntryActivity"
    android:exported="true"
    android:targetActivity="WeiXinHandlerActivity"
    android:theme="@android:style/Theme.Translucent.NoTitleBar" />
    <activity-alias
    android:name="${applicationId}.wxapi.WXEntryActivity"
    android:exported="true"
    android:targetActivity="WeiXinHandlerActivity"
    android:theme="@android:style/Theme.Translucent.NoTitleBar" />

注意事项

从Android11开始, 涉及到一个软件可见性适配问题, 也就是说调起第三方应用时需要在清单文件中声明其对应的包名, 否则无法调起支付, 具体代码如下:

1
2
3
4
5
6
7
8
<queries>
<package android:name="com.eg.android.AlipayGphone" /> <!-- 支付宝 -->
<package android:name="hk.alipay.wallet" /> <!-- AlipayHK -->
<package android:name="com.tencent.mm" /> <!-- 微信支付 -->
<package android:name="com.sina.weibo" /> <!-- 微博 -->
</queries>
<application
...

《Android 11 系统策略更新》

附加

支付宝支付客户端 DEMO&SDK下载

支付宝支付集成文档

微信支付安卓接入指南

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

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

1…141516…48

乱码三千

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

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