踩坑adb——我的一次使用adb命令的踩坑之旅
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了踩坑adb——我的一次使用adb命令的踩坑之旅相关的知识,希望对你有一定的参考价值。
参考技术A 昨晚正在测case的时候,突然冒出来一同事(我们都叫他肖总),来了一句:BUG基(同事都叫我BUG基,你懂的),我这复现了一个问题,但是开发那边说叫我把log导出来,我这不会导,你知道怎么导吗?作为一只BUG基,我怎么可能会放过这个装比的机会呢,哈哈。
叫肖总导log的那个开发啥也没说,就只在jira系统的comments最后写了一句“导出方法:adb pull/cache/recovery/ ./”。其实当时我是崩溃的,我擦,肖总,你妹,这开发不是说了导出方法了吗?你直接复制粘贴打上去命令不就行了吗?然而,装比心理作怪,我还是决定了帮他。
那么下一步是什么?没错,是时候展现装比的技术了!
拿过Pad的第一步,那当然是先装驱动啦。没驱动你怎么使用adb命令?为什么这么说呢。驱动一般指的是设备驱动程序(Device Driver),是一种可以使 计算机 和设备通信的特殊程序。相当于 硬件 的接口, 操作系统 只有通过这个接口,才能控制 硬件 设备的工作,假如某设备的驱动程序未能正确安装,便不能正常工作。那么ADB又是什么东东?Android Debug Bridge,我们一般简称为adb,它是一个非常强大的命令行工具,通过这个工具你能够与你的android设备进行交互。意思也就是说,ADB命令需要通过驱动程序提供的接口来控制硬件设备,因为我们的文件是存储在硬件设备上的呀。
那装驱动要在什么状态下安装?废话,肯定是开机状态啦。当然在安装驱动前,要先开启开发者模式的ADB调试,这里我就不说为什么了,自己想。
那再下一步就是我们要用开发给的adb命令,导出/cache/recovery/这个文件夹的内容。或许有人会问,这开发不是已经给了文件的路劲了吗,直接在Pad上复制粘贴到SD卡又或者直接用PC从Pad复制粘贴到PC就可以了呀。对于这个,我只想说,废话,这么简单的,你会想不到吗?你以为我是猪啊。然而我并不是猪,我是BUG基。
对于上面那个想法,条件并不成立,当我们连接Pad时,windows是屏蔽部分文件的,反正我这里是这个情况,而用Pad直接复制粘贴到SD卡也是不成立,当我复制的时候,会提示“操作失败,目标无法复制”,至于为什么会出现这个提示,请往下看。
既然上面两个方法都不行,那我们就只有用adb命令了。
在执行操作之前,我们要先看移动设备是否跟PC连接,那么就需要用adb devices这个命令查看当前连接的设备,这里可能返回的状态有三种:
I.device设备已经成功连接到了adb-server
II.offline设备并没有连接到adb或者没有响应
III.no device并没有设备/模拟器连接
这里说的三种状态显示的可能跟显示情况不大一样,譬如我连接是正常的,返回的是
或许有人知道这里的意思是什么,但是是否有想到过前面的那个daemon是什么呢?当然有人会说,只要复制粘贴会用就可以了,对于这个回答,我默默表示不回答。
这个daemon还得要从ADB说起,ADB包含了以下三部分的cs模式的程序:
而在解释上图的意思之前,我想先引入两个概念,那就是端口和通信(已理解的可以略过)。
端口
计算机"端口"是英文port的译义,可以认为是计算机与外界通讯交流的出口。其中硬件领域的端口又称接口,如:USB端口、串行端口等。软件领域的端口一般指网络中面向连接服务和无连接服务的通信协议端口,是一种抽象的软件结构,包括一些数据结构和I/O(基本输入输出)缓冲区。
端口最主要的作用就是通信和数据传输,把数据报顺利的传送到目的主机是没有问题的。那么问题出在哪里呢?我们知道大多数 操作系统 都支持多程序(进程)同时运行,那么目的主机应该把接收到的数据报传送给众多同时运行的进程中的哪一个呢?显然这个问题有待解决,端口机制便由此被引入进来。
本地 操作系统 会给那些有需求的进程分配协议端口(protocal port,即我们常说的端口),每个协议端口由一个正整数标识,如:80,139,445,等等。当目的主机接收到数据报后,将根据报文首部的目的端口号,把数据发送到相应端口,而与此端口相对应的那个进程将会领取数据并等待下一组数据的到来。说到这里,端口的概念似乎仍然抽象,那么继续跟我来,别走开。
端口其实就是队, 操作系统 为各个进程分配了不同的队,数据报按照目的端口被推入相应的队中,等待被进程取用,在极特殊的情况下,这个队也是有可能溢出的,不过操作系统允许各进程指定和调整自己的队的大小。
通信
通信(Communication)就是信息的传递,是指由一地向另一地进行信息的传输与交换,其目的是传输消息。其实这里的通信,意思就是说用特定的逻辑信号,实现双方的互相信息传输,譬如说在命令行输入adb devices命令,意思就是说我想要对方输出设备列表给我看,这里的输入”adb devices”就是发送给对方的信号,而输出的设备列表就是对方反馈回来的信号,这个整个过程就是通信的过程。
说了这么多,其目的就在于扫盲,下面我们来说上面提到的ADB三部分的cs模式的程序(我把上面的图拉下来,防止大家看不到):
1) adb client
从图中,我们知道client是运行在PC端的,每当我们发起一个adb命令的时候,就会开启一个client程序。当然,当我们开启DDMS或者ADT的时候,也会自动创建client。
当我们开启一个client的时候,它首先会去检测后台是否已经有一个server程序在运行着,否则会开启一个adb-server进程。
所有的client都是通过5037端口与adb-server进行通信的。
2 ) adb daemon ( adbd )
从图中,我们知道daemon是作为一个后台进程运行在模拟器/真实Android设备中的。
daemon使用端口的范围是5554-5585,每个模拟器/设备连接到PC端时,总会开启这么一个后台进程,并且为其分配了两个连续的端口,比如:
Emulator 1,console: 5554
Emulator 1, adb:5555
也正因为每个设备都分一组两个端口,也已adb连接手机的最大数量为16。
说回端口的作用,在这两个端口中,其中偶数端口是用于server与设备进行交互的,可以让server直接从设备中读取数据,而奇数端口是用来与设备的adbd进行连接通信的。
3) adb server
从图中,我们同样可以知道,server也是作为一个后台的程序运行在PC端的,他负责管理client进程以及adb daemon之间的通信。
当一个server开启的时候,他会自动绑定并且监听5037端口,接收client通过该端口发送过来的命令。同时server还会对5555-5585间的奇数端口进行扫描,进行对已连接设备的定位。
完成了上面一大堆吧啦吧啦的扫盲,大家应该知道了图1的意思了吧,那么我们就要解决问题了。
我们来看开发给我们的adb命令
不知大家是否看到使用adb命令都要在前面输入adb,譬如开发给的“adb pull /cache/recovery/ ./”这个命令就有adb在前面。那么为什么要在命令前面加上一个adb呢,原因在于如果我们不加adb,windows系统会默认为对windows执行命令,而不是通过ADB命令行工具对手机执行操作命令。后面的“pull /cache/recovery/ ./”通过前面学习Linux命令结构(linux命令结构为command [options] [arguments...])大概可知道pull指的是命令动作,后面那两个,指的其实就是参数,/cache/recovery/指的是Pad设备的文件路径,而./指的是当前运行命令行的路劲,譬如下面的提到的C:\Users\301001958这个路径。
好了,继续回到我们的装比之路,刚开始的时候,我不小心把” adb pull /cache/recovery/ ./ ”打成了“adb pull /cache/recovery/./”,也就是,我没有把中间的空格打上,结果弹出了这样的提示,啊,真是瞎了我的眼……
于是,我马上改过来,修改成了“adb pull /cache/recovery/ ./”,结果还是弹出了一样的提示。
我擦,这怎么办怎么办,难道真的要装比不成,反遭雷劈?别急,我们先来看看这里提示的意思,这里的这个remote的意思是指的远端设备,在这指的就是Pad,而object '/cache/recovery/' does not exist的意思就是说Pad的/cache/recovery/这个文件夹对象不存在。
这咋回事啊?怎么会就不存在呢?于是乎,我再进入Recovery mode查看,得到的结果如下:
我擦,这怎么回事?明明有这个文件夹的存在,于是我再次开机在命令行输入adb -help,验证一下这个adb命令的用法,结果吧啦吧啦的出现了一大坨黑色的字,看着都头晕啊,不过还是让我找到了想要的信息,如下图:
看到了这里,我瞬间脸黑了,我靠,这完全就是跟我想的那样没错嘛,怎么就说文件夹对象不存在呢。
于是我还是找上了大家最喜欢的——度娘。找了一番,找到了一个似乎有用的信息,如下图:
正如上面所说,难道是因为没有文件夹没有读写权限?于是,我又输入了adb remount,得出结果如下:
额,看到这里,我不想说话了,不过这里,已经算是弄出了点端倪,大家应该也知道了前面直接在Pad的系统里面复制提示无法复制了吧,最主要就是不够权限的原因,因为一旦系统运行文件随便被更改,系统就有可能出现运行错误或者崩溃。只是我竟天真的以为这里的root,指的是我们经常用的那个一键root软件,只要用软件一键root了,就可以快乐的解决问题了,可想而知,得到的结果依然是像是碰到了蜜蜂窝一样,被蛰着千疮百孔啊,面目全非……这些什么鸟一键root软件,根本就无法root得了我们这些开发中的Pad嘛,还试了一大堆都不行,至于为什么,暂时我没有深究,大家有空可以去研究研究。
到了这里,我只想说:盖伦,请给我一把大宝剑……
无奈,问题最终还是得要解决,于是我继续再找度娘玩去了。
经过了一番查找,我似乎终于找到了答案如何获得root权限了,就是仅仅只需要用“adb root”这个命令就可以让adb获得root权限,二话不说,赶紧开干啊,输入adb root,得出的结果是:adbd restart as root,我擦,蓝瘦香菇,明明只需要几个命令……就可以获得root权限,我为什么能搞得那么复杂,我不行了,盖伦,借你的大宝剑扶我起来……
但是似乎有一件很重要的事是,正因为我前面用了一键root软件,我才能在adb命令使用root权限,前面的功夫也并不是全是无用功,来到这里,我们就只需执行最后一步就是用开发给的命令,把文件拖出来,不过,我把开发给的最后一个参数改了,也就是“./”这个参数,改成了我自己电脑桌面的一个文件夹路径,如我在桌面起了个叫做FileLog的文件夹,如我FileLog的文件夹路径为C:\Users\301001958\Desktop\FileLog,那么我执行的就是adb pull /cache/recovery/ C:\Users\301001958\Desktop\FileLog,然后按Enter执行命令,文件就巴拉拉的复制到了我的FileLog文件夹里面,到这里问题解决完毕。
回顾整个过程,踩的坑着实不少,一个简简单单的命令,一个简简单单的操作,都能把自己搞死,不过在这整个过程里面,也是一个不断扩展知识的过程,也是一个不断挑战自我的过程,到最后的解决,是满心的舒畅。
这整个过程里,给我最大的感悟是,乐于助人,助的有时候不仅仅是别人,助的也是自己,因为在这个过程中,我的知识获得了拓展,获得了成长,也获得了成就感,获得了兴趣,用此文,希望能助正在踩坑的你,走出这个坑,不管是大坑还是小坑,又或者是神坑,在这个写作分享的过程中,也让我对整个知识面理解更全面更深了一步。
文章写得不是那么好,太长了点,请轻喷。
致正在踩坑的你我。 2017.02.26 By BUG基
vue中集成blockly的踩坑之旅
blockly是一款可视化编辑器。
blockly源码下载地址:https://gitee.com/mirrors/blockly?_from=gitee_search
blockly的文档参考网址:
https://itbilu.com/other/relate/Ek5ePdjdX.html#configure-fixed-size
https://www.npmjs.com/package/blockly
请结合以上文档来看这篇博客
初步搭建blockly:
npm install blockly 如果安装失败,请删除node_modules重新安装
在.vue单文件的script中 引入
// 引入Blockly
import Blockly from'blockly'
// 引入想要转换的语言,语言有php python dart lua javascript
import 'blockly/javascript'
// 引入语言包并使用
import * as hans from 'blockly/msg/zh-hans'
Blockly.setLocale(hans);
//引入媒体文件:我是在github上下载的blockly源码,将源码中的media文件放入我项目中的public文件夹下
//忽略被vue错认为组件的blockly中的标签,不止以下这些,请发现一个忽略一个
import Vue from'vue'
Vue.config.ignoredElements.push('xml')
Vue.config.ignoredElements.push('block')
Vue.config.ignoredElements.push('field')
Vue.config.ignoredElements.push('category')
Vue.config.ignoredElements.push('sep')
Vue.config.ignoredElements.push('value')
Vue.config.ignoredElements.push('statement')
Vue.config.ignoredElements.push('mutation')
在.vue单文件的template中确定引入位置并添加工具栏
<!-- blockly工作区 -->
<div id="blocklyDiv" style="height: 480px; width: 600px;"></div>
<!-- blockly工具栏 -->
</xml id="toolbox" style="display: none">
<category name="逻辑" colour="%BKY_LOGIC_HUE">
<block type="controls_if"></block>
<block type="logic_compare"></block>
<block type="logic_operation"></block>
<block type="logic_negate"></block>
<block type="logic_boolean"></block>
</category>
<sep></sep>
<category name="数学" colour="%BKY_MATH_HUE">
<block type="math_number">
<field name="NUM">123</field>
</block>
<block type="math_arithmetic"></block>
<block type="math_single"></block>
</category>
</xml>
<!-- blockly代码区 -->
<textarea name="" id="textarea" cols="30" rows="10"></textarea>
在.vue单文件的script中创建blockly工作区
this.workspace = Blockly.inject('blocklyDiv',
//工具栏
toolbox: document.getElementById('toolbox'),
//网格效果
grid:spacing: 20,length: 3,colour: '#ccc',snap: true,
//媒体资源
media: './media/',
//垃圾桶
trashcan: true
);
//工作区监听代码生成器
this.workspace.addChangeListener(this.myUpdateFunction);
methods:
// 代码生成器
myUpdateFunction(event)
var code = Blockly.JavaScript.workspaceToCode(this.workspace);
document.getElementById('textarea').value = code;
,
// 获取blockly工作区中的code和xml结构
getBlockData()
const code = Blockly.JavaScript.workspaceToCode(this.workspace);
const xml = Blockly.Xml.workspaceToDom(this.workspace)
const xmlText = Blockly.Xml.domToText(xml);
,
// 回显工作区中的xml结构
setBlockData(xmlText)
this.clearBlockData();
const xml = Blockly.Xml.textToDom(xmlText);
Blockly.Xml.domToWorkspace(xml, this.workspace);
,
// 清空工作区
clearBlockData()
this.workspace.clear();
,
报错:[Vue warn]: Unknown custom element: <xml> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
原因:vue将xml标签错认为组件
解决:①引入v-blockly ②Vue.config.ignoredElements.push('xml')所以报类似错误的标签,都要一一忽略
如其他相关问题欢迎提问,乐意为你解答。
以上是关于踩坑adb——我的一次使用adb命令的踩坑之旅的主要内容,如果未能解决你的问题,请参考以下文章