bcoder

Linux下使用dd制作树莓派系统盘

 分类:Linux, Operating System, Others, Others 阅读 (3,309)  Linux下使用dd制作树莓派系统盘已关闭评论
7月 052019
 
一、文章背景

  本文基于Ubuntu16,pi zero WH,树莓派镜像版本2019-06-20_raspbian_full

  树梅派官方推荐使用Etcher制作镜像,但是下载速度实在是太慢了,使用dd也可以搞定。

二、下载镜像

  官网镜像下载地址:https://www.raspberrypi.org/downloads/raspbian/

  首先下载树梅派系统镜像包,是一个zip文件,如:2019-06-20_raspbian_full_latest.zip

  解决zip包后得到img镜像文件,如:2019-06-20-raspbian-buster-full.img

三、准备sd卡

  将sd卡连接电脑,然后执行df -h

  拔掉sd卡后再执行一次df -h

  有变化的那一项即是sd卡的设备名称,如:/dev/sdc1

  /dev/sdc即是sd卡的主设备名,先执行下面命令卸载它的子分区

  假如还有sdc2、sdc3统统卸载掉

四、烧录系统

  执行下面的命令烧录系统

  if=后面是镜像所在的路径

  of=后面是sd卡设备名称

 Posted by on 2019-07-05

关于Gson使用的一些深入研究

 分类:Android, Java 阅读 (1,465)  关于Gson使用的一些深入研究已关闭评论
7月 042019
 
一、Gson的复用

一直有一个担心,对于不同的数据类是否可以用同一个gson实例,今天研究了一下,不仅是可以,而且最好是这样使用。看代码Gson.java中的getAdapter方法,一开始就是在typeTokenCache这个缓存中找type相关的TypeAdapter。

因此复用一个gson的实例会省去匹配TypeAdapter(当然还有new Gson())的时间。

如下代码实例:

在我机器上测试不复用的话用时220-260毫秒之间(非常不稳定),复用120毫秒。

二、TypeToken是个什么东东?

TypeToken其实是为了给标识一个泛型类中的T,对于普通的类我们通过getClass().getName就可以得到类的标识,但是对于泛型类,只能得到泛型外层的类名,并不能得到泛型外层类+泛型类这样的全名。

如下代码:

输出结果是:java.util.ArrayList,而不是java.util.ArrayList<java.lang.Integer>

使用TypeToken来获取就是另外一种情况了,看下面的例子:

输出结果:

三、TypeAdapter的使用

 

四、一些类的作用

1. ConstructorConstructor – 返回一个函数可以给要操作的类新建一个实例对象。

2. InstanceCreator – 用于给没有无参数构造函数的类,创建一个实例的一个接口。解释:gson在反序列时需要创建类的一个实例,如果该类没有无参数构造函数(如:三方库中的类),则会出现异常,所以开发者需要新建一个类实现这个接口,并用该类可用的构造函数新建一个实例。并使用下面方式Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdInstanceCreator()).create();注册到gson中。

3. FutureTypeAdapter – 用于缓存TypeAdapter。为什么不用TypeAdapter的实例缓存?因为TypeAdapter是个虚类 :-D 

 

树莓派无键盘情况下配置无线网络

 分类:Others, Others 阅读 (2,917)  树莓派无键盘情况下配置无线网络已关闭评论
7月 032019
 

转载自:http://shumeipai.nxez.com/2017/09/13/raspberry-pi-network-configuration-before-boot.html

 

不算是什么新功能了,在树莓派3B发布后不久,树莓派官方 Raspbian 系统久加入了允许在开机前对 WiFi 网络进行配置的机制。

注意,这个方法仅适用于全新安装树莓派系统到 SD 卡之后没有做过任何 Wi-Fi 配置的情况下有效。如果你之前配置过 Wi-Fi,再用本方法系统会默认使用已有的配置而忽略这里的配置。因此建议使用前重新安装系统。

一、WiFi 网络配置

用户可以在未启动树莓派的状态下单独修改 /boot/wpa_supplicant.conf 文件配置 WiFi 的 SSID 和密码,这样树莓派启动后会自行读取 wpa_supplicant.conf 配置文件连接 WiFi 设备。

操作方法简单:将刷好 Raspbian 系统的 SD 卡用电脑读取。在 boot 分区,也就是树莓派的 /boot 目录下新建 wpa_supplicant.conf 文件,按照下面的参考格式填入内容并保存 wpa_supplicant.conf 文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
country=CN
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
 
network={
ssid="WiFi-A"
psk="12345678"
key_mgmt=WPA-PSK
priority=1
}
 
network={
ssid="WiFi-B"
psk="12345678"
key_mgmt=WPA-PSK
priority=2
scan_ssid=1
}

说明以及不同安全性的 WiFi 配置示例:
#ssid:网络的ssid
#psk:密码
#priority:连接优先级,数字越大优先级越高(不可以是负数)
#scan_ssid:连接隐藏WiFi时需要指定该值为1

如果你的 WiFi 没有密码

1
2
3
4
network={
ssid="你的无线网络名称(ssid)"
key_mgmt=NONE
}

如果你的 WiFi 使用WEP加密

1
2
3
4
5
network={
ssid="你的无线网络名称(ssid)"
key_mgmt=NONE
wep_key0="你的wifi密码"
}

如果你的 WiFi 使用WPA/WPA2加密

1
2
3
4
5
network={
ssid="你的无线网络名称(ssid)"
key_mgmt=WPA-PSK
psk="你的wifi密码"
}

如果你不清楚 WiFi 的加密模式,可以在安卓手机上用 root explorer 打开 /data/misc/wifi/wpa/wpa_supplicant.conf,查看 WiFi 的信息。

二、开启 SSH 服务

如果通过 ssh 连接树莓派出现 Access denied 这个提示则说明 ssh 服务没有开启。要手动开启的话,和 WiFi 配置相似,同样在 boot 分区新建一个文件,空白的即可,文件命名为 ssh。注意要小写且不要有任何扩展名。
树莓派在启动之后会在检测到这个文件之后自动启用 ssh 服务。随后即可通过登录路由器找到树莓派的 IP 地址,通过 ssh 连接到树莓派了。(有关开启 SSH 服务的详细方法

如果需要远程桌面方式操作树莓派,可以通过 ssh 安装 xrdp,再用 Windows 的远程桌面客户端连接到树莓派

这个小技巧对于没有有线网卡、没有标准 USB 接口来直连键鼠,但集成了 WiFi 的树莓派 Zero W 尤其实用。

 Posted by on 2019-07-03

ByteBuffer详解

 分类:Android, Java, Java语言 阅读 (6,015)  ByteBuffer详解已关闭评论
7月 022019
 
一、ByteBuffer的父类

  ByteBuffer的父类是Buffer类,意思为缓冲区类,ByteBuffer为字节缓冲区,当然他也可以处理int, long, char等基本数据类型。

  相比于Buffer类的其他继承类CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer 和 ShortBuffer,ByteBuffer类应用更广泛。

 
二、ByteBuffer的几个变量
position 表示当前bytebuffer的数据指针的位置。因为ByteBuffer还可以做为一个数据解析器,比如getShort()可以读出来一个short类型的数据,因此position也是很重要的。
limit 读取时可用作数据索引的上限(此时相当于数据的length – 1),但是写入时又不能有这个limit,否则会造成数据无法写入(写入时可设置limit = capacity)
mark 用于标记读取数据的起始位置,比如我们已经处理完成10个字节的数据,以后不用再管这10个字节,那么我们可以用mark()标记一下,然后配套的时候reset使position回到这个位置(比如后边的处理遇到了异常,或者遇到了不完整的数据)。
capacity 容量,很简单啦,就是最大允许的字节数量。
 
三、几个要点

  1、limit的设置,因为put和get系列函数只会影响position,不会影响limit,limit是数据的结尾位置,是相当的重要。

 
四、ByteBuffer类的方法
put(byte b) 向ByteBuffer中写入一个字节,并且如果成功position+1
put(byte[] src) 将参数中的byte数据写入bytebuffer中,并且如果成功position+src的长度
put(byte[] src, int offset, int length) 将src数组中,在offset处开始,长度为length的数据写入到ByteBuffer中,并且如果成功,position+length
compact() 其实就是删除已读过的数据,将position到limit之间的数据移动到0和limit-position处,并将mark重置为-1,position放到数据结尾,总结一下,就是可以继续写数据了,但是不能读数据。
limit() 获取当前的数据尾的位置(当然,前提是你设置过limit或者调用过flip)
limit(int newLimit) 设置数据的结尾位置。
rewind() 执行后position = 0, mark = -1,数据内容不变。应用场景:新put数据后,使用rewind将指针位置恢复到起始位置。
reset() 将position恢复到mark处的位置。
clear() 重置ByteBuffer的 position = 0; limit = capacity; mark = -1,实际数据内容无变化,其实这个函数会比较少用,不如rewind的实用性强,因为rewind不会改变limit。
remaining() 还未读取的数据limit – position,前提是你正确设置了limit的位置(所有数据的结尾位置)或者调用过flip()函数。
hasRemaining() 是否还有未读取的数据,前提是你正确设置了limit的位置(所有数据的结尾位置)或者调用过flip()函数。
mark() 将当前的position设备为mark(),mark要和reset配合使用。
discardMark() 将mark的位置重置为-1,貌似很少会单独使用这个函数,而是用rewind或者clear来重置mark值
flip() 其实这个函数的意思是,数据准备好了,可以读了,估计是reset、rewind、clear这些名字用的差不多了,起了一个这个难理解的名字,翻转,听着就让人晕。这个函数相当于下面两个函数的组合buf.limit(buf.position());
buf.rewind();。
get系列函数  
 Posted by on 2019-07-02

Android Studio中引入编译好的so文件

 分类:Android, Java 阅读 (2,407)  Android Studio中引入编译好的so文件已关闭评论
6月 252019
 

so文件单纯的放在源码libs目录下是不能编译到apk中的,需要下面的步骤才可以使用so文件。

一、首先将so文件放到app/src/main/libs目录下,so文件在libs目录下或者libs子目录下均可

二、修改build.gradle(app)文件,在defaultConfig节中加入下面代码

三、然后调用so文件就可以了

 Posted by on 2019-06-25

Android编译系统(mk)路径变量整理

 分类:Android, Java 阅读 (5,095)  Android编译系统(mk)路径变量整理已关闭评论
6月 062019
 

本文基于Android8.1系统源码,常量的定义在文件./build/make/core/envsetup.mk中

TOPDIR – 源码根目录

OUT_DIR – out目录,默认情况下是源码目录下的out目录,如果指定OUT_DIR_COMMON_BASE这个环境变量,则为这个变量指定的目录

TARGET_BUILD_TYPE – 是release还是debug的编译,在环境变量TARGET_BUILD_TYPE中指定

SOONG_OUT_DIR – soong目录,默认情况下是out/soong

DEBUG_OUT_DIR – TARGET_BUILD_TYPE为debug时会用到此目录,默认是out/debug

TARGET_OUT_ROOT – target目录,默认是out/target,debug时为out/debug/target

TARGET_PRODUCT_OUT_ROOT – 默认是out/target/product目录

TARGET_COMMON_OUT_ROOT – 默认是out/target/common目录,用于生成编译时的中间文件

PRODUCT_OUT – 默认是out/target/product/{设备型号},真正的编译生成文件的目录

TARGET_OUT – $(PRODUCT_OUT)/system目录

TARGET_OUT_GEN – $(PRODUCT_OUT)/gen

TARGET_OUT_EXECUTABLES – $(TARGET_OUT)/bin

TARGET_OUT_OPTIONAL_EXECUTABLES – $(TARGET_OUT)/xbin

TARGET_OUT_RENDERSCRIPT_BITCODE := $(TARGET_OUT_SHARED_LIBRARIES)

TARGET_OUT_JAVA_LIBRARIES :=$(PRODUCT_OUT)/system/framework

TARGET_OUT_APPS :=$(PRODUCT_OUT)/system/app

TARGET_OUT_APPS_PRIVILEGED :=$(PRODUCT_OUT)/system/priv-app

TARGET_OUT_KEYLAYOUT :=$(PRODUCT_OUT)/system/usr/keylayout

TARGET_OUT_KEYCHARS :=$(PRODUCT_OUT)/system/usr/keychars

TARGET_OUT_ETC :=$(PRODUCT_OUT)/system/etc

TARGET_OUT_FAKE := $(PRODUCT_OUT)/fake_packages

TARGET_OUT_TESTCASES := $(PRODUCT_OUT)/testcases

HOST_OUT_ROOT – host目录,默认是out/host

HOST_OUT

SOONG_HOST_OUT

HOST_CROSS_OUT

 Posted by on 2019-06-06

Android编译系统命令总结

 分类:Android, Java 阅读 (1,289)  Android编译系统命令总结已关闭评论
6月 062019
 

本文基于Android8.1系统源码

– lunch: lunch <product_name>-<build_variant>
– tapas: tapas [<App1> <App2> …] [arm|x86|mips|armv5|arm64|x86_64|mips64] [eng|userdebug|user]
– croot: 回到源码根目录.
– cproject 回到当前项目的根目录
– m: 从根目录开始编译,相当于make整个系统.
– mm: 编译当前目录下的所有模块,但不包括他们的依赖.
– mmm: 编译指定目录下的所有模块,但不包括他们的依赖,.
To limit the modules being built use the syntax: mmm dir/:target1,target2.
– mma: 编译当前目录下的所有模块,包括他们的依赖.
– mmma: 编译指定目录下的所有模块和他们的依赖.
– provision: Flash device with all required partitions. Options will be passed on to fastboot.
– cgrep: 在所有的c或者c++文件中搜索某个关键字.
– ggrep: 在所有的gradle文件中搜索某个关键字.
– jgrep: 在所有的java文件中搜索某个关键字.
– resgrep: 在所有的资源文件中搜索某个关键字.
– mangrep: 在所有的AndroidManifest.xml文件中搜索某个关键字.
– mgrep: 在所有的Makefiles文件中搜索某个关键字.
– sepgrep: 在所有的sepolicy文件中搜索某个关键字.
– sgrep: 在所有的源代码文件中搜索某个关键字.
– rcgrep: 在所有的rc文件中搜索某个关键字
– godir: 跳转到包含某个文件的目录中某个关键字.

具体的函数实现可以查看build/envsetup.sh

 Posted by on 2019-06-06
4月 252019
 
一、启动init进程

init程序是Linux启动的和经一个程序

init程序的源文件在system/core/init/init.cpp里

二、解析init.rc

在init的main函数里,会先做一些系统初始化的工作,然后通过Parser对象来解析init.rc文件

parser对象的源文件在system/core/init/init_parser.cpp里面

在8.1系统源码里面,rc文件分别存在几个不同的目录里面

  • 主rc文件,init.rc在device/设备名/型号名/目录里,init.rc通过import的形式导入其他的rc文件
  • 还有一些其他的rc文件也在这个目录里面
  • init.zygote.rc文件在system/core/rootdir里面

但是在把系统镜像烧录到车机后,rc文件都在根目录/下

三、启动zygote

init进程解析完init.rc,将根据配置文件启动zygote

zygote是所有安卓服务和应用的父进程,承载着创建java虚拟机并且孵化安卓层的SystemServer和安卓应用的功能

zygote源码在frameworks/base/cmds/app_process/app_main.cpp中

四、启动SystemServer

在zygote中其实并没有fork出来一个SystemServer,而是先启动了java层的ZygoteInit类(通过runtime.start(“com.android.internal.os.ZygoteInit”, args, zygote))

当然fork是不能java层直接调用的,ZygoteInit.java中又通过Zygote类,Zygote类又通过jni调用了Linux层的函数fork出来了SystemServer

ZygoteInit.java的源码在:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

Zygote.java的源码在:frameworks/base/core/java/com/android/internal/os/Zygote.java

Zygote jni层的代码在:frameworks/base/core/jni/com_android_internal_os_Zygote.cpp

SystemServer启动后,会启动一大堆系统服务,安卓的基础运行环境就起来了,启动服务的几个函数为:

SystemServer的代码在:frameworks/base/services/java/com/android/SystemServer.java

五、Launcher的启动

在SystemServer的startOtherServices函数中调用了mActivityManagerService.systemReady,

在ActivityManagerService的systemReady函数中通过startHomeActivityLocked来启动Launcher

六、待续问题:

init.rc中的服务是怎么启动的

 Posted by on 2019-04-25

一个计算角度的类

 分类:Android, Java 阅读 (818)  一个计算角度的类已关闭评论
4月 062019
 

本代码是个半成品,只作为参考

使用时,将此类作为android组件放到布局中即可

计算红线与绿线之间的角度,效果图如下:

代码如下:

 

 Posted by on 2019-04-06
3月 262019
 

一、必要的系统环境

  硬盘200G,内存4G+,交换分区(swap)4G+(可装完系统后添加,见后面错误处理部分)

二、下载源码,国内可以在清华镜像站下载 

  地址:https://mirrors.tuna.tsinghua.edu.cn/help/AOSP/

  网上有很多教程,这里就不再累述了

三、然后安装编译时需要的三方库

sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip

安装open-jdk-8

sudo add-apt-repository ppa:openjdk-r/ppa

sudo apt-get update

sudo apt-get install openjdk-8-jdk

四、开始编译

  然后进入到Android源码目录,假设源码在用户根目录的aosp目录中:

cd ~/aosp

  然后初始化编译环境,使用下面的命令:

source build/envsetup.sh

  然后选择要编译的目标版本,先输入lunch命令

lunch

  然后在显示的列表中选择你的目标版本,输入相应的数字,按回车即可

  然后使用make开始编译,可以使用-j参数增加编译的线程以提高速度,线程数量为cpu核心数的2倍比较合适,比如你的cpu是4核的使用

make -j8

  就可以了

五、遇到的错误

1、错误1:

03:00:11 ckati failed with: signal: killed
build/core/main.mk:21: recipe for target ‘run_soong_ui’ failed
make: *** [run_soong_ui] Error 1

解决方案1:
增加swap空间
增加办法:
cd /
增加4个G的交换空间
sudo dd if=/dev/zero of=/swp bs=10M count=400
sudo mkswap /swp
sudo swapon /swp

用free -m查看交换空间的情况
这个方法增加的是临时交换空间,如需一直保留,需要其他操作
参考链接:
https://blog.csdn.net/yellow_hill/article/details/38894317

解决方案2:
export LC_ALL=C

 

2、错误2:
JackServer提示out of memory

解决方案1:
增加虚拟机内存至最少4G

解决方案2:
修改jack server内存
步骤:
打开./prebuilts/sdk/tools/jack-admin
找到下面这一行
JACK_SERVER_VM_ARGUMENTS=”${JACK_SERVER_VM_ARGUMENTS:=-Dfile.encoding=UTF-8}”
修改为
JACK_SERVER_VM_ARGUMENTS=”${JACK_SERVER_VM_ARGUMENTS:=-Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx4096M}”
保存jack-admin文件
在命令行执行
./prebuilts/sdk/tools/jack-admin kill-server
./prebuilts/sdk/tools/jack-admin start-server
重启jack server
然后重新编译

3、错误3:

Error while parsing ‘/media/liuderu/新加卷/android-8.0.0_r1/out/target/common/obj/APPS/QuickSearchBox_intermediates/with-local/classes.dex.flags’:1

原因:路径中包含中文字符

4、错误4

FAILED: out/target/common/obj/PACKAGING/checktestapi-current-timestamp

先执行一次make update-api然后再执行make

 Posted by on 2019-03-26