C/C++ printf 列印 size_t 的方法

本篇將介紹在 C/C++ 程式裡如何 printf 印出 size_t 這個變數類型,最常用到就是 vector::size(),或者是其它 STL 容器的 size() 也是如此。

這邊舉例用 printf 印出 vector 的 size,如下例程式,

cpp-printf-size_t.cpp
1
2
3
4
5
6
7
8
9
// g++ cpp-printf-size_t.cpp -o a.out -std=c++11
#include <iostream>
#include <vector>
using namespace std;

int main() {
vector<int> v = {1, 2, 3, 4, 5};
printf("size=%d", v.size());
}

編譯後會得到一個編譯警告,如下所示,

1
2
cpp-printf-size_t.cpp:8:31: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘std::vector<int>::size_type {aka long unsigned int}’ [-Wformat=]
printf("size=%d", v.size());

透過查詢後得知 size 回傳型態是 size_type,size_type 又定義成 size_t,

size_t 在 printf 要用 %zu,順便補充一下,ssize_t 在 printf 要用 %zd
改成這樣後再編譯一次就沒有出現 compile warning 了,

cpp-printf-size_t2.cpp
1
2
3
4
5
6
7
8
9
// g++ cpp-printf-size_t2.cpp -o a.out -std=c++11
#include <iostream>
#include <vector>
using namespace std;

int main() {
vector<int> v = {1, 2, 3, 4, 5};
printf("size=%zu", v.size());
}

參考
c - How can one print a size_t variable portably using the printf family? - Stack Overflow
https://stackoverflow.com/questions/2524611/how-can-one-print-a-size-t-variable-portably-using-the-printf-family
What is the correct way to use printf to print a size_t in C/C++?
https://www.tutorialspoint.com/what-is-the-correct-way-to-use-printf-to-print-a-size-t-in-c-cplusplus

其它相關文章推薦
C/C++ 新手入門教學懶人包
32/64bit 作業系統 printf 列印 int64_t / uint64_t 的方法

Android 系列文章

這邊整理一下 Android 系列文章,目前本人大多關注於 Android Platform 的開發,Android App 琢磨較少。

以下為 ShengYu 的 Android 系列教學 (陸續更新中…):

基礎
Android 架構 - 了解整個 Android 架構
如何編譯 Build Android - 從下載 AOSP(Android Open Source Project) 到編譯 Android
如何寫 Android.mk - 如何寫 Android.mk,編譯出執行檔、靜態函式庫、動態函式庫,以及如何連結至靜態函式庫/動態函式庫
如何寫 Android.bp - 如何寫 Android.bp

深入進階文章
Android.mk 的運作原理 - 介紹 Android.mk 的編譯流程與運作原理
如何看 Android Platform 的 PLATFORM_VERSION 版本?
從 Android.mk 到 Android.bp

工具
Android 安裝 Busybox (adb shell 使用 vi)
Android adb 基本用法教學
Android adb logcat 基本用法教學
Android adb 同步時間/設定時間
Android adb 取得電池 battery 電量資訊
Android fastboot 基本用法教學
Android fastboot 查詢當前使用的a/b槽
Android systrace 基本用法教學
Android adb forward 通訊埠轉發用法教學
Android adb shell input 事件用法

其他
Android USB Tethering 透過 USB 分享行動數據

如何寫 Android.bp

本篇記錄一下如何寫 Android.bp,並附上基本範例與原本的 Android.mk 對照。

基本範例

以下就以AOSP上的sdcard模組來做作為範例,完整路徑在system/core/sdcard/Android.bp下。

system/core/sdcard/Android.bplink
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
cc_binary {
srcs: ["sdcard.cpp"],
name: "sdcard",
cflags: [
"-Wall",
"-Wno-unused-parameter",
"-Werror",
],
shared_libs: [
"libbase",
"libcutils",
"libminijail",
],
sanitize: {
misc_undefined: ["integer"],
},
}

cc_binary:表示編譯成執行檔
srcs:原始檔
name:模組名稱,也是執行檔名稱
cflags:編譯參數
shared_libs:連結的動態函式庫

可以跟原先的 Android.mk 對照看就大概了解了,原本的 Android.mk 如下:

system/core/sdcard/Android.mklink
1
2
3
4
5
6
7
8
9
10
11
12
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES := sdcard.cpp fuse.cpp
LOCAL_MODULE := sdcard
LOCAL_CFLAGS := -Wall -Wno-unused-parameter -Werror
LOCAL_SHARED_LIBRARIES := libbase libcutils libminijail libpackagelistparser

LOCAL_SANITIZE := integer

include $(BUILD_EXECUTABLE)

LOCAL_SRC_FILES 對應到 srcs
LOCAL_MODULE 對應到 cc_binary
LOCAL_CFLAGS 對應到 cflags
LOCAL_SHARED_LIBRARIES 對應到 shared_libs
BUILD_EXECUTABLE 對應到 cc_binary

參考
[1] Android编译系统中的Android.bp、Blueprint与Soong · 零壹軒·笔记
https://note.qidong.name/2017/08/android-blueprint/

OpenCV FileStorage 用法與 YAML 檔案讀取寫入範例

本篇介紹如何使用 OpenCV 的 FileStorage 來做 YAML 檔案格式的寫入與讀取,在 OpenCV 許多應用都需要使用資料的儲存於讀取,例如相機的3D校正需要儲存校正後的結果矩陣,以利下次使用;在機器學習的應用上需要將訓練學習得到的參數保存等。OpenCV 提供了 XML/YAML 檔案格式作儲存與讀取,以下將介紹如何使用 FileStorage 來讀取與寫入 YAML。

FileStorage 使用介紹

FileStorage 的使用流程如下:

  1. 初始化一個 FileStorage 的變數並且開檔
  2. 使用 << 進行資料的寫入,>> 進行資料讀取,類似 C++ 中的檔案操作
  3. 使用 FileStorage::release() 函數釋放記憶體與關檔

使用 FileStorage 寫入資料

以下範例示範開檔、寫入int數值、寫入矩陣、寫入系統時間,最後關檔。

opencv-FileStorage-write.cpp
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
// g++ opencv-FileStorage-write.cpp `pkg-config --cflags --libs opencv`
#include <time.h>
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

bool writeYaml() {
std::string filename = "output.yaml";
cv::FileStorage fs(filename, FileStorage::WRITE);
if (!fs.isOpened()) {
cout << "failed to open file " << filename << endl;
return false;
}

// write int
int imageWidth= 5;
int imageHeight= 10;
fs << "imageWidth" << imageWidth;
fs << "imageHeight" << imageHeight;

// write a Mat
cv::Mat m1= Mat::eye(3, 3, CV_8U);
cv::Mat m2= Mat::ones(3, 3, CV_8U);
cv::Mat resultMat= (m1+1).mul(m1+2);
fs << "resultMat" << resultMat;

// write multi-variables
cv::Mat cameraMatrix = (Mat_<double>(3,3) << 700, 0, 320, 0, 700, 240, 0, 0, 1);
cv::Mat distCoeffs = (Mat_<double>(5,1) << 0.1, 0.01, -0.001, 0, 0);
fs << "cameraMatrix" << cameraMatrix << "distCoeffs" << distCoeffs;

// write local time
time_t rawtime;
time(&rawtime); // #include <time.h>
fs << "calibrationDate" << asctime(localtime(&rawtime));

fs.release();
return true;
}

int main(int argc, const char *argv[])
{
writeYaml();
return 0;
}

使用 FileStorage 讀取資料

opencv-FileStorage-read.cpp
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
// g++ opencv-FileStorage-read.cpp `pkg-config --cflags --libs opencv`
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

bool readYaml() {
std::string filename = "output.yaml";
cv::FileStorage fs(filename, FileStorage::READ);
if (!fs.isOpened()) {
cout << "failed to open file " << filename << endl;
return false;
}

int width;
int height;
fs["imageWidth"] >> width;
fs["imageHeight"] >> height;
cout << "width = " << width << endl;
cout << "height = " <<height << endl;

// read Mat
cv::Mat resultMatRead;
fs["resultMat"] >> resultMatRead;
cout << "resultMat = \n" << resultMatRead << endl;

cv::Mat cameraMatrix, distCoeffs;
fs["cameraMatrix"] >> cameraMatrix;
fs["distCoeffs"] >> distCoeffs;
cout << "cameraMatrix = \n" << cameraMatrix << endl;
cout << "distCoeffs = \n" << distCoeffs << endl;

// read string
string timeRead;
fs["calibrationDate"] >> timeRead;
cout << "calibrationDate = " << timeRead << endl;

fs.release();
return true;
}

int main(int argc, const char *argv[])
{
readYaml();
return 0;
}

輸出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
width = 5
height = 10
resultMat =
[ 6, 2, 2;
2, 6, 2;
2, 2, 6]
cameraMatrix =
[700, 0, 320;
0, 700, 240;
0, 0, 1]
distCoeffs =
[0.1;
0.01;
-0.001;
0;
0]
calibrationDate = Wed Dec 18 23:04:36 2019

參考
[1] OpenCV: cv::FileStorage Class Reference
https://docs.opencv.org/3.4.8/da/d56/classcv_1_1FileStorage.html
[2] OpenCV —數據持久化: FileStorage類的數據存取操作與示例 - iracer的博客
https://blog.csdn.net/iracer/article/details/51339377
[3] 使用OpenCV的FileStorage模塊持久化存取數據(Python)
http://zhaoxuhui.top/blog/2018/06/29/PythonOpenCVFileStorage.html

其它相關文章推薦
怎麼查詢 OpenCV 的版本
如何看OpenCV當初編譯的編譯參設定
OpenCV trace VideoCapture 流程

Android USB Tethering 透過 USB 分享行動數據

本篇介紹如何使用 Android USB Tethering 的功能,這個功能可以讓你的電腦透過 Android USB 分享行動數據,這功能背後技術是使用 RNDIS(Remote Network Driver Interface Specification) 的協定。

透過下列指令查看目前 usb 的設定是在什麼模式下。

1
$ adb shell getprop persist.sys.usb.config

輸出

1
mtp,adb

透過下列指令即可開啟 RNDIS 的功能,也可以從設定>更多>網路共用與可攜式無線網路基地台>USB網路用,此時 android 會長出 rndis0 的網路介面,電腦端應該會長出一個 usb0 的網路介面(有可能被重命名)。

1
$ adb shell setprop persist.sys.usb.config rndis,adb

參考
[1] Android USB Tethering
https://wiki.gentoo.org/wiki/Android_USB_Tethering
[2] 使用 USB 行動數據分享 (USB Tethering)
https://artistehsu.pixnet.net/blog/post/273206803
[3] Android USB 属性设置:ADB、RNDIS、MTP等
https://blog.csdn.net/u012247418/article/details/84674793
[4] 如何讓 embedded device 透過手機上網 – USB Tethering – SZ Lin & Embedded Linux
https://szlin.me/2016/08/26/%e5%a6%82%e4%bd%95%e8%ae%93-embedded-device-%e9%80%8f%e9%81%8e%e6%89%8b%e6%a9%9f%e4%b8%8a%e7%b6%b2-usb-tethering/

C++ std::unordered_map 用法與範例

本篇介紹 C++ 的 std::unordered_map 用法,一開始會先介紹 unordered_map 的概念,再來是 unordered_map 的用法教學,並提供一些範例參考。

std::unordered_map 與 std::map 的區別
C++ STL 中 map 裡面的存放資料是有序(排序)的,map 對應的資料結構是紅黑樹(red-black tree),紅黑樹是一種自平衡的二元搜尋樹,在紅黑樹上做搜尋的時間複雜度為O(logN)。而 unordered_map 裡面的存放資料是無序的,unordered_map 對應雜湊表(hash table),雜湊表的特點就是搜尋效率高,利用鍵值與雜湊函數(hash function)計算出雜湊值而快速的查找到對應的元素,時間複雜度為常數級別O(1), 而額外空間複雜度則要高出許多。unordered_map 與 map 的使用方法基本上一樣,都是 key/value 之間的映射,只是他們內部採用的資料結構不一樣。所以對於需要高效率查詢的情況可以使用 unordered_map 容器。而如果對記憶體消耗比較敏感或者資料存放要求排序的話則可以用 map 容器。

以下 C++ unordered_map 內容將分為這幾部份,

  • unordered_map 初始化
  • unordered_map 容器裡插入元素與存取元素
  • unordered_map 容器裡移除元素
  • 使用迴圈尋訪 unordered_map 容器
  • 清空 unordered_map 容器
  • 判斷 unordered_map 容器是否為空
  • unordered_map 使用範例

要使用 unordered_map 容器的話,需要引入的標頭檔<unordered_map>

unordered_map 初始化

以下為 unordered_map 初始化容器的寫法,

1
2
3
4
5
std::unordered_map<std::string, int> umap = {
{"Tom", 1},
{"Ann", 4},
{"Jack", 2}
};

unordered_map 容器裡插入元素與存取元素

unordered_map 容器插入元素有兩種寫法,
第一種是使用中括號 [] 的方式來插入元素,很像陣列的寫法,例如:umap[key] = value,範例如下,

1
2
3
std::unordered_map<std::string, int> umap;
...
umap["John"] = 3;

另一種是使用 umap.insert() 成員函式來插入元素,
那這個 umap.insert() 方式跟上面中括號 [] 的方式有什麼不同呢?

差別在於如果 key 值已經存在的話,使用中括號 [] 的方式會將新資料覆蓋舊資料,
而使用 umap.insert() 的方式會回傳插入的結果,該 key 值存在的話會回傳失敗的結果,
檢查 umap.insert() 的插入結果方式如下,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <string>
#include <unordered_map>

int main() {
std::unordered_map<std::string, int> umap;
umap.insert(std::pair<std::string, int>("John", 3));

std::pair<std::unordered_map<std::string, int>::iterator, bool> retPair;
retPair = umap.insert(std::pair<std::string, int>("John", 3));

if (retPair.second == true)
std::cout << "Insert Successfully\n";
else
std::cout << "Insert Failure\n";

return 0;
}

unordered_map 容器要取得某 key 鍵值元素的話可以這樣寫,

1
std::cout << "id: " << umap["John"] << "\n";

unordered_map 容器裡移除元素

以下為 unordered_map 容器裡移除元素的寫法,移除第一個元素的寫法像這樣,

1
2
3
std::unordered_map<std::string, int> umap;
...
umap.erase(umap.begin());

unordered_map 容器移除指定元素的寫法,

1
2
3
std::unordered_map<std::string, int> umap;
...
umap.erase("Ann");

unordered_map 容器移除某段範圍元素的寫法,下例示範從 John 開始移除到尾部的範圍,

1
2
3
std::unordered_map<std::string, int> umap;
...
umap.erase(umap.find("John"), umap.end());

使用迴圈尋訪 unordered_map 容器

這邊示範用 for 迴圈尋訪 unordered_map 裡面的元素,並且將它們印出來,寫法如下,

1
2
3
for (const auto& n : umap) {
std::cout << "name: " << n.first << ", id: " << n.second << "\n";
}

另一種迴圈尋訪 unordered_map 的方法是使用迭代器,以下示範使用前向迭代器,改用 auto 的話可以讓 code 更簡潔,

1
2
3
4
5
for (std::unordered_map<std::string, int>::iterator it = umap.begin(); it != umap.end(); it++) {
// or
// for (auto it = umap.begin(); it != umap.end(); it++) {
std::cout << "name: " << (*it).first << ", id: " << (*it).second << "\n";
}

清空 unordered_map 容器

要清空 unordered_map 容器的的話,要使用 clear()

1
2
3
std::unordered_map<std::string, int> umap;
...
umap.clear();

判斷 unordered_map 容器是否為空

要判斷 unordered_map 是否為空或是裡面有沒有元素的話,可以用 empty(),寫法如下,

1
2
3
4
5
6
7
8
std::unordered_map<std::string, int> umap;
umap.clear();

if (umap.empty()) {
std::cout << "empty\n";
} else {
std::cout << "not empty, size is "<< umap.size() <<"\n";
}

unordered_map 使用範例

std-unordered_map.cpp
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
// g++ std-unordered_map.cpp -o a.out -std=c++11
#include <iostream>
#include <string>
#include <unordered_map>

int main() {
std::unordered_map<std::string, int> umap = {
{"Tom", 1},
{"Ann", 4},
{"Jack", 2}
};

for (const auto& n : umap) {
std::cout << "name: " << n.first << ", id: " << n.second << "\n";
}

umap["Tiffany"] = 5;
umap["John"] = 3;

std::cout << umap["John"] << "\n";
std::cout << umap["Tiffany"] << "\n";

for (std::unordered_map<std::string, int>::iterator it = umap.begin(); it != umap.end(); it++) {
// or
// for (auto it = umap.begin(); it != umap.end(); it++) {
std::cout << "name: " << (*it).first << ", id: " << (*it).second << "\n";
}
}

輸出如下:

1
2
3
4
5
6
7
8
9
10
name: Jack, id: 2
name: Tom, id: 1
name: Ann, id: 4
3
5
name: John, id: 3
name: Tiffany, id: 5
name: Jack, id: 2
name: Tom, id: 1
name: Ann, id: 4

參考
std::unordered_map - cppreference.com
https://en.cppreference.com/w/cpp/container/unordered_map
unordered_map - C++ Reference
http://www.cplusplus.com/reference/unordered_map/unordered_map/
unordered_map in C++ STL - GeeksforGeeks
https://www.geeksforgeeks.org/unordered_map-in-cpp-stl/
C++ STL 之哈希表 | unordered_map | 「浮生若梦」 - sczyh30’s blog
https://www.sczyh30.com/posts/C-C/cpp-stl-hashmap/
C++ STL unordered_map介紹與使用方法 - Cypress的博客 - CSDN博客
https://blog.csdn.net/Cypress1010/article/details/53669409
雜湊表 - 維基百科,自由的百科全書
https://zh.m.wikipedia.org/zh-tw/%E5%93%88%E5%B8%8C%E8%A1%A8
雜湊函式 - 維基百科,自由的百科全書
https://zh.m.wikipedia.org/wiki/%E6%95%A3%E5%88%97%E5%87%BD%E6%95%B8

其它相關文章推薦
如果你想學習 C++ 相關技術,可以參考看看下面的文章,
C/C++ 新手入門教學懶人包
std::map 用法與範例
std::multimap 用法與範例
std::vector 用法與範例
std::deque 用法與範例
std::queue 用法與範例

如何編譯 Build Android AOSP

記錄下 Android 要怎麼編譯 build AOSP (Android Open Source Project)。

1
2
3
$ source build/envsetup.sh
$ lunch
$ make -j4

source build/envsetup.sh 之後才能用 mm 或 mmm 指令。
lunch 後面可接 target。
要跑模擬器的話選擇 lunch aosp_arm-eng 然後 make 完後下 emulator 指令。

aosp_arm-eng 的 aosp_arm 是產品名稱,後面的 eng 是 engineer 的意思,另外還有 user、userdebug

Buildtype 說明
user 編譯出來的系統有一定的權限限制, 常用於產品發佈階段
userdebug 編譯出來的系統有 root 權限, 常用於開發測試除錯
eng engineer 版本

make -j4-j4 是代表讓電腦使用幾個執行緒進行編譯,這樣能提高編譯速度,這個值取決於開發機器的CPU數、核心數與執行緒數,以四核心CPU的電腦為例,就可以使用 -j4 這參數,
如果CPU有支援超執行緒(HT, Hyper-Threading)的話就可以使用 -j8

要編譯單一模組的話,可以在 make 後面加上模組名稱,以下為常用的模組:

make <目標模組> 說明
make kernel 編譯 kernel,輸出 boot.img
make bootimage 產生 boot.img
make userdataimage 產生 userdata.img
make recoveryimage 產生 recovery.img
make cacheimage 產生 cache.img

產出的 boot.img、system.img 在out/target/product/目錄下
接下來就介紹一下 Android 的各種映像檔

Android 的映像檔

名稱 說明
boot.img 包含kernel啟動參數, kernel等多個元素?
ramdisk.img 一個小型的檔案系統, 是 Android 系統啟動的關鍵
system.img Android 的, framework 也在這裡, 將被掛載到 /system 目錄下
recovery.img 「救援模式」時使用的映像檔
cache.img 緩衝區, 將被掛載到 /cache 目錄下
misc.img 各種雜項
userdata.img 各程式的資料儲存地,將被掛載到 /data 目錄下
metadata.img
vendor
radio
tos

參考
[1] Building Android | Android Open Source Project
https://source.android.com/setup/build/building
[2] 理解Android編譯命令- Gityuan博客
http://gityuan.com/2016/03/19/android-build/
[3] Partitions and Images | Android Open Source Project
https://source.android.com/devices/bootloader/partitions-images
https://blog.csdn.net/tuhuolong/article/details/44681037
https://www.twblogs.net/a/5b8e41662b7177188343df5e

Android fastboot 基本用法教學

本篇介紹如何在 Android 下使用 fastboot 指令,fastboot 是開發 Android 時常用到的工具,使用 fastboot 指令可對 android 裝置進行燒錄,以下將介紹如何安裝與基本使用。

Google 官方的 SDK Platform Tools release notes 有各版本的釋出說明。

Windows 安裝方式

從官方下載 Windows 最新版
目前最新版為 platform-tools_r34.0.5-windows.zip

Mac 安裝方式

從官方下載 Mac 最新版
目前最新版為 platform-tools_r34.0.5-darwin.zip

透過 brew 安裝

1
$ brew install android-platform-tools

Ubuntu 安裝方式

從官方下載 Linux 最新版
目前最新版為 platform-tools_r34.0.5-linux.zip

透過 apt 安裝

1
2
$ sudo apt update
$ sudo apt install android-tools-fastboot

fastboot 指令基本教學,進入 fastboot mode 工程模式

Android 裝置進入 fastboot mode 模式有兩種方式,
方法1,如果 Android 已經是開機完的狀態,可以使用下列 adb 指令讓 Android 裝置進入到 fastboot mode 模式,

1
$ adb reboot bootloader

方法2,如果 Android 是關機狀態,可以使用 Android 裝置上的按鈕鍵讓 Android 開機時進入 fastboot mode 模式,每支 Android 手機對應的按法不太一樣,請參考這裡,大部分都是開機時長按電源鍵(Power)與音量下鍵(Volume Down)。

解除退出離開 fastboot mode 工程模式

Android 裝置在 fastboot mode 模式時,如果我們想要離開/退出/解除 fastboot mode 模式的話,可以輸入下列 fastboot 指令,就會退出fastboot mode 模式讓 Android 裝置重新開機回到作業系統,

1
$ fastboot reboot

fastboot 常用指令選項

以下為常用的 fastboot 指令,有想到在陸續增加吧!
sudo fastboot devices︰查看裝置
sudo fastboot reboot︰重新開機
sudo fastboot reboot-bootloader︰重新開機且進入 bootloader
sudo fastboot flash boot boot.img︰燒錄 kernel 區
sudo fastboot flash system system.img︰燒錄系統區
sudo fastboot flash vendor vendor.img︰燒錄
sudo fastboot flash persist persist.img︰燒錄
sudo fastboot flash userdata userdata.img︰燒錄使用者資料區,包含一些安裝的軟體
sudo fastboot oem device-info︰查詢裝置的基本資訊
sudo fastboot oem [COMMAND...]︰執行 oem 的特定指令
sudo fastboot oem unlock︰新的 android 裝置需要用sudo fastboot flashing unlock指令。解鎖 bootloader 開機載入器、解除鎖定後才能刷 boot.img,可能會失去保固與手機資料,包含照片、影片、文件、app,請記得備份
sudo fastboot getvar <變數名>︰查詢裝置 bootloader 的某個變數
sudo fastboot getvar all︰查詢裝置 bootloader 的所有變數
sudo fastboot set_active <a/b>︰切換 a/b 槽
sudo fastboot help︰查看說明

小技巧:使用 fastboot boot boot.img 下載 boot.img 載入 kernel 到記憶體開機試用,不會真的燒錄進去,這樣可以測試看看這個 boot.img 是否能正常開機,如果無法正常開機只要重新開機就什麼復原了。指令下完後,它 download 完 boot.img 會接著開機,不需再下額外的指令。

參考
[1] 刷機小教室-簡易 fastboot 教學-開發者交流區
https://www.asus.com/zentalk/tw/thread-215625-1-1.html
[2] Android Fastboot 与 Recovery 和刷机 - 简书
https://www.jianshu.com/p/d960a6f517d8
有系統分區示意圖

Android fastboot 查詢當前使用的a/b槽可以看這篇
上一篇是Android adb指令的安裝與用法教學,有空看看吧~

Android fastboot 查詢當前使用的a/b槽

紀錄一下如何使用 Android 的 fastboot 指令查詢 android 裝置目前使用那個槽(a/b),知道是哪個槽後,比較能確定之後要燒錄哪個槽。

查詢目前使用那個槽(a/b), 看目前的slot是a還是b,一般都是a。

1
$ sudo fastboot getvar current-slot

參考
[1] adb - fastboot set_active command does not exist - Android Enthusiasts Stack Exchange
https://android.stackexchange.com/questions/203124/fastboot-set-active-command-does-not-exist

其它相關文章推薦
基本的Android fastboot指令用法教學與安裝可以看這篇

Android adb 取得電池 battery 電量資訊

本篇紀錄一下怎麼用 Android 查詢取得電池 battery 電量狀態,透過 adb 指令來取得電池電量資訊。

查詢 andoid 裝置電池 battery 剩餘電量資訊

1
$ adb shell dumpsys battery | grep level

參考
[1] android - Is it possible to query device state (ie. battery charge remaining) via ADB shell command? - Stack Overflow
https://stackoverflow.com/questions/42274720/is-it-possible-to-query-device-state-ie-battery-charge-remaining-via-adb-shel
[2] Android adb shell dumpsys battery 電池電量狀態 @ 不專業。工程師 :: 痞客邦 ::
http://blog.stepbystep.tw/blog/post/118831503