android刷机的一些事

android

Posted by 101142ts on March 2, 2020

android编译及刷机的一些事

因为疫情的原因,很长一段时间难以回校,但是实验还是要继续进行,所以需要远程完成编译Android和刷机工作。在这之中我走了很多的弯路,所以今天写篇BLOG记录一下。

同步Android源码到本地

这部分需要注意的是同步时可以使用清华源来同步。

Driver Binaries

  • 如果直接将下载好的Android源代码编译,并将镜像刷到手机上,会出现一个问题:就是虽然可以正常的刷机,但是刷机后的手机里的/data/目录是空的,这样子我们就不能往手机上安装应用。

问题出在我们没有将google官方的Driver Binaries一同编译:地址

adb && fastboot

adb和fastboot有很多很常见的问题。首先需要注意的是,adb和fastboot不要使用ubuntu自带的,一定要去官网下载最新的包!

  • adb/fastboot devices看不到我们想要的设备

这里其实有两种可能性,一种是lsusb里也看不到相应的设备,另外一种是lsusb里可以看到。

  • 如果lsusb内可以看到,但是adb devices里看不到

首先考虑有没有将设备编号写入/etc/udev/rules.d/51-android.rules文件中,写入的格式如下:

SUBSYSTEM=="usb", ATTRS{idVendor}=="0bb4", MODE="0666", GROUP="adbusers"

写完以后要记得把自己添加到相应的用户组中,然后使用以下命令:

# Restart UDEV
sudo udevadm control --reload-rules
sudo service udev restart
# Restart the ADB server
adb kill-server
# Replug your Android device and verify that USB debugging is enabled in developer options
adb devices

正常来说到此就能够使用adb devices了。如果还是不行,可以尝试一下软件模拟插拔,软件模拟插拔的代码为:

/* usbreset -- send a USB port reset to a USB device */

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>

#include <linux/usbdevice_fs.h>


int main(int argc, char **argv)
{
    const char *filename;
    int fd;
    int rc;

    if (argc != 2) {
        fprintf(stderr, "Usage: usbreset device-filename\n");
        return 1;
    }
    filename = argv[1];

    fd = open(filename, O_WRONLY);
    if (fd < 0) {
        perror("Error opening output file");
        return 1;
    }

    printf("Resetting USB device %s\n", filename);
    rc = ioctl(fd, USBDEVFS_RESET, 0);
    if (rc < 0) {
        perror("Error in ioctl");
        return 1;
    }
    printf("Reset successful\n");

    close(fd);
    return 0;
}

如果设备在lsusb中的编号是

Bus 001 Device 113: ID 18d1:4ee2 Google Inc. Nexus 4 (debug)

则可以使用以下命令模拟插拔

usbreset /dev/bus/usb/001/113
  • adb/fastboot devices能看到,但无法操作

使用软件模拟插拔基本能解决问题

  • lsusb也看不到

没救了

永不锁屏&&永不睡眠?

毕竟是远程调试,如果可以的话,我还是希望能够获取屏幕的。经过多方的实验,我发现要获取屏幕必须满足一下两个条件:

  • 屏幕没锁屏

参考这里 可以完美实现不锁屏

  • 屏幕没熄灭

试了好多个方案都不行,不过这个还没试过

刷机的一键脚本

首先如果在Android的主目录内直接使用命令

 fastboot -w flashall

会报如下的错误

fastboot: error: ANDROID_PRODUCT_OUT not set

一开始我以为设置了ANDROID_PRODUCT_OUT就可以了,我设置的目录是./out/target/product/hammerhead,但是我发现这样子刷机会出问题,报如下的错误:

Checking 'product'                                 OKAY [  0.100s]
Snapshot cancel                                    FAILED (remote: 'unknown command')
fastboot: error: Command failed

折腾来折腾去,我发现其实可以通过如下的命令自动设置这个ANDROID_PRODUCT_OUT

. build/envsetup.sh
lunch 5

由于我想刷的机器不止一台,所以我就想通过写一个自动化脚本来帮我完成这个功能。经过摸索,我发现

. build/envsetup.sh

的功能其实和下面的代码的功能完全一样

./build/envsetup.sh

但如果你在python3内使用os.system或者是subprocess.run来执行./build/envsetup.sh,会报如下的错误:

./build/envsetup.sh: 1: ./build/envsetup.sh: Syntax error: "(" unexpected

这个问题让我百思不得其解,为啥同样的指令,在终端里就能执行,而在python3内就没办法执行呢?后来我才发现这是因为./build/envsetup.sh这个文件它没有以shebang打头,所以如果在python3内执行的话,默认是使用/bin/sh来解释的。

同样的,lunch指令其实是./build/envsetup.sh这个文件内的一个函数,所以如果你在python3内分开执行这两条指令,它会提示你

>>> os.system('lunch 5')
sh: 1: lunch: not found

所以这里我能想到的自动化生成刷机脚本的方式是,拷贝一份./build/envsetup.sh文件,在文件的最后写入

lunch 5
adb -s 05dcf6150acd9321 reboot bootloader
fastboot -s 05dcf6150acd9321 -w flashall

然后执行拷贝后的文件。

轻松切换jdk版本

以前我是通过这个命令来修改的

sudo update-alternatives --config java

但是编译android时需要修改的不止java,还有javac等。

然后我搜到了以下的脚本,不得不说,简直天才好吧。

#!/bin/sh
echo ‘start eclipse’
case $1 in
    jdk6)
 export JAVA_HOME=/usr/lib/jvm/jdk1.6.0_45/
 ;;
    openjdk7)
 export JAVA_HOME=~/Desktop/zulu7.36.0.5-ca-jdk7.0.252-linux_x64/
 ;;
esac
echo $JAVA_HOME
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib

使用的时候只需要即可

. ~/Desktop/Android6.0.0_r23/switch_java.sh openjdk7

openjdk7

编译Android6.0.0时需要openjdk7,但是openjdk7在ubuntu18.04上已经被移除了,你也不能够通过以下命令安装

sudo add-apt-repository ppa:openjdk-r/ppa  
sudo apt-get update   
sudo apt-get install openjdk-7-jdk  

解决方法是到这里下载openjdk7

下载并设置完以后,需要修改/build/core/main.mk文件。