adb用法

启动 App

adb shell monkey -p com.android.settings -c android.intent.category.LAUNCHER 1

列出 app

adb shell pm list packages

发送广播

adb root
adb shell am broadcast -a android.intent.action.BOOT_COMPLETED

android集成X5浏览器

参考博文

https://blog.csdn.net/qq_34205629/article/details/122375262

下载内核

android studio 打开 X5Demo(官方 demo),

  1. 点击”TBS 调试“
  2. 点击”安装线上内核“
  3. 控制台查看日志输入:
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
{
"BUGLY" : 0,
"DOWNLOADMAXFLOW" : 300,
"DOWNLOADURL" : "https://tbstx.imtt.qq.com/others/release/x5/tbs_core_046317_20221125231059_nolog_fs_obfs_arm64-v8a_release.tbs",
"DOWNLOAD_FAILED_MAX_RETRYTIMES" : 10,
"DOWNLOAD_MIN_FREE_SPACE" : 0,
"DOWNLOAD_SINGLE_TIMEOUT" : 1200000,
"DOWNLOAD_SUCCESS_MAX_RETRYTIMES" : 3,
"MSG" : "success, dcl:103846,url:102237",
"PKGMD5" : "0b8d4f9faecea88015064b34092ffd82",
"RESETDECOUPLECORE" : 0,
"RESETTODECOUPLECORE" : 0,
"RESETTOKEN" : 1,
"RESETX5" : 0,
"RESPONSECODE" : 1,
"RET" : 0,
"TBSAPKFILESIZE" : 52874442,
"TBSAPKSERVERVERSION" : 46317,
"TEMPLATESWITCH" : 0,
"UPLOADLOG" : 0,
"USEBACKUPVER" : 0,
"USEVIDEO" : 1,
"USEX5" : 1,
"USE_SECURITY" : 0
}

android镜像解压资源文件

工具准备

  1. unpackbootimg
  2. resource-tool
  3. dtc
  4. rk 烧录工具

编译 unpackbootimg

源码

https://github.com/huangzhenzeng/android-unpackbootimg

编译

只需要在 linux(需安装 gcc,make,一般是标配)或 windows(需要安装 mingw)的命令行执行 make,即可产生可执行文件 mkbootimg、unpackbootimg

resource-tool 工具

一般编译镜像后,将产生这个工具,目录为:
u-boot/tools/resource_tool/resource_tool

dtc 工具

一般编译镜像后,将产生这个工具,目录为:
kernel/scripts/dtc/dtc

rk 烧录工具

需到如下地址
https://www.t-firefly.com/doc/download/54.html
下载《RKDevTool》

分离镜像

window 下,打开“RKDevTool”,选中“高级”,然后导入固件,选择解压即可,如下图:

最终 output 目录,输出各个子分区,如下图:

解压 boot.img 镜像

boot 格式分析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
因为boot.img的格式比较简单,它主要分为三大块(有的可能有四块)
+—————–+
| boot header | 1 page
+—————–+
| kernel | n pages
+—————–+
| ramdisk | m pages
+—————–+
| second stage | o pages
+—————–+
n = (kernel_size + page_size – 1) / page_size
m = (ramdisk_size + page_size – 1) / page_size
o = (second_size + page_size – 1) / page_size
0. all entities are page_size aligned in flash
1. kernel and ramdisk are required (size != 0)
2. second is optional (second_size == 0 -> no second)

linux 下输入命令:
mkdir output
unpackbootimg -I boot.img -O ./output
生成文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
├── boot.img-base (mkbootimg base参数)
├── boot.img-board
├── boot.img-cmdline (mkbootimg cmdline参数)
├── boot.img-dtb
├── boot.img-hash
├── boot.img-kerneloff
├── boot.img-oslevel
├── boot.img-osversion
├── boot.img-pagesize (mkbootimg pagesize参数)
├── boot.img-ramdisk.gz (根文件系统打包文件)
├── boot.img-ramdiskoff
├── boot.img-second (资源文件)
├── boot.img-secondoff
├── boot.img-tagsoff
├── boot.img-zImage (内核文件)

解压 boot.img-second 资源

执行命令:
mkdir out
./resource_tool --verbose --unpack --image=boot.img-second

生成文件如下:

1
2
3
├── logo.bmp
├── logo_kernel.bmp
└── rk-kernel.dtb

dtb 转 dts

执行命令:
./dtc -I dtb -O dts out/rk-kernel.dtb -o tmp.dts
生成 tmp.dts 文件,

最终通过 gedit 或文本编辑查看

ParcelFileDescriptor使用说明

文件描述符,是一种程序读写已打开文件、socket 的对象。

FileDescriptor 对象,它代表了原始的 Linux 文件描述符
ParcelFileDescriptor 对象,是原始文件描述符的一个复制,对象跟 fd 不同,但都是操作同一个底层文件流以及文件位置指针

简单的 ParcelFileDescriptor 使用——pipe

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
public class DemoParcefliledescriptor extends AppCompatActivity {

private static final String TAG = "DemoPFD";

private static final String[] PERMISSIONS = {
Manifest.permission.WRITE_EXTERNAL_STORAGE,
};
private static final int PERMISSIONS_CODE = 3006;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo_null);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(PERMISSIONS, PERMISSIONS_CODE);
}

FileOutputStream outputStream = new FileOutputStream(getStreamFd());
try {
outputStream.write(99);
outputStream.write(98);
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}


private FileDescriptor getStreamFd() {
ParcelFileDescriptor[] pipes = null;

try {
pipes = ParcelFileDescriptor.createPipe();
new TransferThread(new ParcelFileDescriptor.AutoCloseInputStream(pipes[0])).start();
} catch (IOException e) {
e.printStackTrace();
}

return pipes[1].getFileDescriptor();
}

static class TransferThread extends Thread {
InputStream in;
FileOutputStream out;

TransferThread(InputStream in, FileOutputStream out) {
this.in = in;
this.out = out;
}

TransferThread(InputStream in) {
this.in = in;

File outFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/zlq_pdf");
Log.i(TAG, "File: " + outFile.getAbsolutePath());

try {
out = new FileOutputStream(outFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}

@Override
public void run() {
byte[] buf = new byte[1024*2];

int len;
try {
while((len=in.read(buf)) > 0) {
out.write(buf, 0, len);
Log.i(TAG, "out:" + len);

}

in.close();
out.flush();
out.getFD().sync();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

编译rk3399板子android10系统(ubuntu22.4)

  1. 前提条件
    编译主机内存至少 12G,交换内存 10G(swapfile),磁盘空间 150G

  2. 解压 android10
    cat rk_android_10_sdk.tar.gz* | tar xzvf

  3. 进入解压根目录
    cd rk_android_10_sdk

  4. 切换终端
    exec bash
    注意:zsh 会有问题

  5. 安装 openjdk8

  6. 安装 python2.7
    sudo apt install python2.7

  7. 安装基础库

1
2
3
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 libssl-dev gawk liblz4-tool

sudo apt-get install libncurses5 libncurses5:i386
  1. 执行 sh javaenv.sh

  2. 执行 source build/envsetup.sh

  3. 执行 lunch
    出现菜单中,选择 6 rk3399_Android10-userdebug

  4. 如果修改 framework,需要
    make api-stubs-docs-update-current-api

  5. 执行 ./build.sh -UKAu

常见问题

  1. GLIBCXX_3.4.21 not defined in file libstdc++.so.6 with link time reference
1
2
3
4
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt-get update
sudo apt-get install gcc-5
sudo apt-get upgrade libstdc++6

android多路摄像头

原生 Android-Camera 类打开一个摄像头没有问题,打开多个会在 open()的时候报错。

注意原生 camera 要在 surface 之后在 open,否则会报错。也就是说不要直接在 oncreate 里 open。(相机 Open 前要设置 surface ,这个 surface 就是底层用来渲染预览画面的,如果 surface 都没有 create ,底层将无法渲染,我想这就是为什么 open 不了的原因吧)参考:https://bbs.csdn.net/topics/390940480

理论上,好像原生 camera 最大支持打开两个摄像头,可以参考这个代码去实现:

https://blog.csdn.net/a87636764/article/details/54645350

当然也可以看下面这个代码(比较全):

https://blog.csdn.net/CrossFile_TMS/article/details/75258570

但实际打开第二个我就报错了,报错内容:

W/CameraBase: An error occurred while connecting to camera: 1

java.lang.RuntimeException: Fail to connect to camera service

试了很多次都不行,果断放弃了原生 Camera 的思路,转向了 UVC 的方向:(下面详细写了,先膜拜一下 orz)

可以看下这个大哥的实现:https://blog.csdn.net/yyfd2013/article/details/85321175

UVCCamera 项目在 open 位置又报错了:解决 UVCCamera 项目报错:could not open camera:err=-1

参考地址:https://www.jianshu.com/p/21e95f2f1206

———————————— 我是分界线 ————————————

我去,总算搞出来了,看了一天的源码,调了一天的 bug。。。。。。

效果图如下:

主要参考了下面的项目:

UVC-Github 项目源码地址:https://github.com/saki4510t/UVCCamera

然后能搜到的是下面这两个博客:

单摄像头 github:https://github.com/jiangdongguo/AndroidUSBCamera

单摄像头 CSDN:https://blog.csdn.net/andrexpert/article/details/78324181


多路摄像头 github:https://github.com/yyfd2013zy/UvcCameraDemo

多路摄像头 CSDN:https://blog.csdn.net/yyfd2013/article/details/85321175


然后这篇文章是解析了代码,但我还是希望小伙伴们能自己去看源码,自己去消化,别人的始终不是自己的:

https://www.jianshu.com/p/9108ddfd0a0d

其中,学习的话我更偏向于多路摄像头那个项目,他用的是源码导入;而单摄像头的项目是作者自己封装了,并且我的直观感受是和源项目结构差不多,这样一封装层级结构更多了,查找源码找 bug 太复杂了。。。不过单摄像头的项目功能封装的比较多一些。

我的需求是多路摄像头的可视化 + 拍照,并且是 IOT 设备,所以倾向于多路摄像头项目。

没有不经历汗水就能拿到奖的人,资料和学习路线我都放上面了,剩下的坑要自己去趟了!

———————————— 我还是分界线 ————————————

环境:rk3288 5.1 海康摄像头


填坑之路:

首先像这么复杂的项目导入肯定是编译不过。。。一定要看清楚原博主写的经验:

传送门:https://blog.csdn.net/momo0853/article/details/73898066 看了,和官网一样,墙内用户放心下。

项目配置好 NDK 路径(是项目,别把 android studio 改了。。),clean 一下应该就没问题了。

项目跑起来之后,你会发现。。。是黑屏的。。。(一般是)

这个只能说自己的硬件,自己写日志慢慢调试吧,不同的摄像头和主板肯定不一样。项目的核心关键类是:UVCCamera

问题基本出现在下面几个方面:

1.分辨率。看源码,默认分辨率是 640*480,要看你的摄像头支不支持,不支持的话会打开成功,但是黑屏。

2.首选 FRAME_FORMAT_MJPEG,可以都换成这个试一试,如果不行,再换 FRAME_FORMAT_YUYV。我是全部 FRAME_FORMAT_MJPEG 就可以了。

3.因为各种原因导致的 open 错误,可以看英文解释:

github:https://github.com/worlfChina/UVCCameraDemo

下载后请更换项目 NDK 为您本地 r14 版本。

android源码打开日志开关

android 系统中日志及对应的等级大小为:
VERBOSE < DEBUG < INFO < WARN < ERROR

android 底层源码通过宏开关控制相应等级的日志输出。
经常在源码看到这个宏的定义
#define LOG_NDEBUG 0

如果宏被注释掉,那么只输出DEBUG及以上的日志,如果要输出全部日志,去掉该条宏定义的注释即可。