Alain's Blog

  1. 首页
  2. Android
  3. 正文

使用Termux安装xfce4桌面, Android Studio, Code Server(VSCode)

2023年10月19日 5540点热度 32人点赞 2条评论

Termux安装xfce4桌面环境

使用Android设备使用Termux,Termux-x11安装xfce4桌面环境,并安装Android Studio,Code Server(VSCode)等软件,搭配Termux-API,Termux-Widget配置快捷启动图标

转载请注明出处,本文仅用于学习交流,不对之处,恳请指正 ,部分图片摘取网络,如有侵权请联系

开源工具

termux-toy 作者很谦虚,说只是个开源玩具(啊?好像作者是我自己)

# 推荐清空数据后使用
bash <(curl -fsSL https://raw.githubusercontent.com/AlainLam/termux-toy/main/start.sh)

Termux系列软件安装包

安装包

Termux:https://f-droid.org/repo/com.termux_118.apk
Termux-x11:https://github.com/termux/termux-x11/suites/16954107083/artifacts/968612187
Termux-API:https://f-droid.org/repo/com.termux.api_51.apk
Termux-Widget:https://f-droid.org/repo/com.termux.widget_13.apk

Termux初始化安装

# 安装库
pkg install x11-repo root-repo -y

# 更新
pkg upgrade -y

# 安装openssh(可选)
pkg install openssh

# 设置密码
passwd

# 获取存储权限(可选)
termux-setup-storage

# 安装桌面相关软件
pkg install termux-x11-nightly pulseaudio virglrenderer-android -y

Termux中安装proot-distro,并安装Debian系统

pkg install proot-distro -y
proot-distro install debian

Debian安装浏览器等常用软件,并新增普通用户

  1. 登录进debian系统

    proot-distro login debian --shared-tmp
  2. 安装软件以及配置

    # 更新
    apt-get update && apt-get dist-upgrade -y
    
    #安装软件
    apt-get install sudo nano wget firefox-esr p7zip-full -y
    
    # 新增用户,并按提示输入信息
    adduser alain
  3. 给普通账户添加sudo权限

    nano /etc/sudoers

    在 root ALL=(ALL:ALL) ALL 之后添加 alain ALL=(ALL:ALL) ALL , 就像下面这样

    # User privilege specification
    root    ALL=(ALL:ALL) ALL
    alain   ALL=(ALL:ALL) ALL
  4. 加入到video跟audio的用户组

    usermod -aG audio,video alain

Debian安装xfce4桌面环境,并解决中文乱码

  1. 切换到普通用户

    su - alain
  2. 安装桌面

    sudo apt install xfce4 xfce4-goodies
  3. 设置时区

    sudo ln -sf /usr/share/zoneinfo/Hongkong /etc/localtime
  4. 解决中文乱码

    ##### 解决中文乱码
    # 参考: https://wiki.archlinuxcn.org/wiki/Locale
    # 命令行环境还是使用英语比较友好,所以我的设置均为en_US.UTF-8,你可以自行替换为zh_CN.UTF-8
    #
    # 安装语言环境以及文泉驿字体
    # sudo apt install locales fonts-wqy-zenhei -y
    # 安装区域环境以及思源字体
    sudo apt install locales fonts-noto-cjk -y
    # 生成区域设置
    sudo dpkg-reconfigure locales
    # 选择97. en_US.UTF-8 UTF-8
    # 回车后选择3. en_US.UTF-8
    # 相当于nano /etc/locale.gen取消注释en_US.UTF-8 UTF-8后,locale-gen
    # 设置系统区域
    # 因为无法使用localectl set-locale LANG=en_US.UTF-8
    # 所以直接设置到配置文件当中
    # echo "LANG=en_US.UTF-8" > /etc/locale.conf

    你可以单独设置用户的语言环境(可选)

    nano ~/.profile

    写入以下代码(locale输出内容)

    LANG=en_US.UTF-8
  5. 安装输入法

    sudo apt install fcitx5* -y

    编辑~/.profile,追加以下代码

    # Use the fcitx5 im
    GTK_IM_MODULE=fcitx
    QT_IM_MODULE=fcitx
    XMODIFIERS=@im=fcitx
    SDL_IM_MODULE=fcitx
    GLFW_IM_MODULE=ibus
    
    if [ ! -d ~/log ]; then
        mkdir -p ~/log
    fi
    fcitx5 > ~/log/im.log 2>&1 &

Termux安装VSCode(Code-Server)

如果不需要VSCode(Code-Server),你可以直接跳过并进入下一节
注意,此节是在Debian环境中,并切换到普通用户

安装VSCode(Code-Server)

# 创建下载目录
mkdir ~/Downloads

# 进入下载目录
cd ~/Downloads

# 下载 comandlline工具
wget https://github.com/coder/code-server/releases/download/v4.17.1/code-server-4.17.1-linux-arm64.tar.gz

# 解压
mkdir -p ./tmpcoder
tar -xvf code-server-*.tar.gz -C ./tmpcoder/

# 创建目录
mkdir -p ~/Applications

# 移动VSCode到对应目录并删除临时目录
mv ./coder/code-server-* ~/Applications/coder
rm -rf ./tmpcoder

# 如果~/.config/code-server不存在,则先创建它
mkdir ~/.config/code-server

# 创建配置文件,注意修改其中的值
echo "bind-addr: 127.0.0.1:${code_server_port}
auth: password
password: ${code_server_pwd}
cert: false" > ~/.config/code-server/config.yaml

# 运行
~/Applications/coder/bin/code-server

Termux安装Android Studio

如果不需要Android Sutdio,你可以直接跳过并进入下一节
注意,此节是在Debian环境中,并切换到普通用户

安装JDK 17(Proot-distro中的Android Studio必须JDK17以上)

sudo apt install openjdk-17-jre -y

安装Android SDK(Commandline-tools)

# 创建下载目录
mkdir ~/Downloads

# 进入下载目录
cd ~/Downloads

# 下载 comandlline工具
wget https://dl.google.com/android/repository/commandlinetools-linux-10406996_latest.zip

# 解压
unzip commandlinetools-linux-*.zip

# 创建目录
mkdir -p ~/Android/Sdk/cmdline-tools/latest

# 移动工具到对应目录
mv ~/Downloads/cmdline-tools/* ~/Android/Sdk/cmdline-tools/latest/

# 进入该目录
cd ~/Android/Sdk/cmdline-tools/latest/bin/

# 默认同意全部许可申请
yes | ./sdkmanager --licenses

配置Android环境变量

  1. 在~/.profile中追加以下代码

    # Android Environments
    export ANDROID_HOME=$HOME/Android/Sdk
    export ANDROID_USER_HOME=$HOME/.android
    export ANDROID_EMULATOR_HOME=$ANDROID_USER_HOME
    export ANDROID_AVD_HOME=$ANDROID_EMULATOR_HOME/avd/
    export PATH=$PATH:$ANDROID_HOME/tools:$ANDROID_HOME/tools/bin:$ANDROID_HOME/platform-tools
  2. 使它生效

    source ~/.profile

安装Android Studio

# 进入下载目录
cd ~/Downloads

# 下载Android Studio
wget https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2022.3.1.20/android-studio-2022.3.1.20-linux.tar.gz

# 解压
tar -xvf android-studio-*-linux.tar.gz

# 移动工具到Android studio目录
mv ./android-studio ~/Android

Termux修复aapt2等编译工具问题

https://github.com/termux/termux-packages/issues/8350
https://github.com/lzhiyong/android-sdk-tools
https://github.com/lzhiyong/android-sdk-tools/releases

# 进入下载目录
cd ~/Downloads

# v34.0.3
wget https://github.com/lzhiyong/android-sdk-tools/releases/download/34.0.3/android-sdk-tools-static-aarch64.zip

# v33.0.3
# wget https://github.com/lzhiyong/android-sdk-tools/releases/download/33.0.3/android-sdk-tools-static-aarch64.zip

# 解压
unzip android-sdk-tools-static-aarch64.zip

# 创建目录
mkdir ~/Android/android-sdk-tools

# 移动到指定目录
mv platform-tools ~/Android/android-sdk-tools/
mv build-tools ~/Android/android-sdk-tools/

自动软链接aapt2等编译工具

此节是为了以后下载其他版本的SDK时,自动替换对应的编译工具,具有一定的性能损耗
而且很多设备并不足以支持inotify的运行
如果不需要,并希望手动管理,则可以跳过此节

  1. 脚本需要使用到inotifywait命令,所以需要安装inotify-tools

    sudo apt install inotify-tools -y
  2. 创建存放脚本的目录,你可以放在你喜欢的文件夹当中,我喜欢把自定义脚本放在同一个文件夹中

    mkdir ~/scripts
  3. 编写脚本

    nano ~/scripts/fix_sdk_tools.sh

    写入以下代码

    #!/bin/bash
    # Author: https://www.alainlam.cn
    
    #### 定义变量
    ANDROID_SDK_PATH=$ANDROID_HOME
    MONITOR_DIRS=("platform-tools" "build-tools")
    TARGET_DIRS=("/home/alain/Android/android-sdk-tools")
    
    #### 下载编译工具
    # if [ ! -d "$TARGET_DIRS" ]; then
    #     mkdir -p ~/Download && cd ~/Downloads
    #     # v34.0.3
    #     wget https://github.com/lzhiyong/android-sdk-tools/releases/download/34.0.3/android-sdk-tools-static-aarch64.zip
    #     # 解压
    #     unzip android-sdk-tools-static-aarch64.zip
    #     # 创建目录
    #     mkdir $TARGET_DIRS
    #     # 移动到指定目录
    #     mv platform-tools $TARGET_DIRS
    #     mv build-tools $TARGET_DIRS
    # fi
    ####
    
    #### 监听SDK目录文件变化
    checking_files() {
        local checking_file=$1
        file_name=$(basename "$checking_file")
    
        # 如果是目录的话,需要重新遍历整个目录
        # 因为可能是整个目录移入的情况
        if [ -d "$checking_file" ]; then
            files=($(ls "$checking_file"))
            for file in "${files[@]}"; do
                checking_files "$checking_file/$file"
            done
        else
            # 跳过已经是软链接的文件
            if [ ! -L "$checking_file" ]; then
                target_file=""
                for dir in "${TARGET_DIRS[@]}"; do
                    # 检查编译工具目录中是否有对应的文件
                    target_file=$(find "$dir" -name "$file_name" -type f -print -quit)
                    # 如果找到文件就中止循环
                    if [ -n "$target_file" ]; then
                        break
                    fi
                done
    
                # 找到对应的编译工具文件
                if [ -n "$target_file" ]; then
                    # 删除原来的编译工具文件
                    rm -rf "$checking_file"
                    # 创建软链接
                    ln -s "$target_file" "$checking_file"
                    echo "Created symlink $checking_file -> $target_file"
                fi
            fi
        fi
    }
    
    # 设置文件监听
    inotifywait --exclude '^.*\.temp/.*$' -mrq -e create,move "$ANDROID_SDK_PATH" | while read -r directory event file; do
        for monitor_dir in "${MONITOR_DIRS[@]}"; do
            if [[ "$directory$file" =~ "$ANDROID_SDK_PATH$monitor_dir" ]]; then
                checking_files "$directory$file"
            fi
        done
    done
    ####
  4. 修改权限

    chmod 700 ~/scripts/fix_sdk_tools.sh
  5. 在~/.profile调用它

    nano ~/.profile

    追加以下代码

    bash ~/scripts/fix_sdk_tools.sh > ~/log/sdktools.log 2>&1 &

修复NDK问题

https://github.com/lzhiyong/termux-ndk/releases/tag/ndk-r23

# 进入下载目录
cd ~/Downloads

# 下载lzhiyong编译号的NDK,有需要的话你也可以自己编译
# https://github.com/Lzhiyong/termux-ndk/tree/master/docs
wget https://github.com/lzhiyong/termux-ndk/releases/download/ndk-r23/android-ndk-r23c-aarch64.zip

# 解压
unzip android-ndk-r23c-aarch64.zip

# 移动至目标目录
mv ./android-ndk-r23c $ANDROID_HOME/ndk/

后续你需要在你项目的gradle.properties文件中配置ndk的目录,效果类似这样的

## This file must *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
#Sat Oct 07 18:42:35 UTC 2023
sdk.dir=/home/alain/Android/Sdk
ndk.dir=/home/alain/Android/Sdk/ndk/android-ndk-r23c

修复模拟器导致无法运行程序的问题

https://developer.android.com/studio/emulator_archive
这并不能在termux中运行Android emulator
后续我会进行一些尝试
理论上来说,如果装上了qemu的话,应该或许可能是可行的

# 进入下载目录
cd ~/Downloads

# 下载emulator-linux_x64的版本
wget https://redirector.gvt1.com/edgedl/android/repository/emulator-linux_x64-10696886.zip

# 解压缩
unzip emulator-linux_x64-*.zip

# 拷贝到对应的文件夹
mv ./emulator $ANDROID_HOME/

# 下载package.xml
wget https://public-static.alainlam.cn/7g5mAuLfebuSyWOv/package.xml -O $ANDROID_HOME/emulator/package.xml

# 需要注意的是如果你下载的emulator跟我的版本不同的话
# 你需要自行修改package.xml中的内容中的32为你下载的emulator版本
# <revision><major>32</major><minor>1</minor><micro>15</micro></revision> 

到这里,我们已经准备好Android的编译环境了

Android12以上修复Termux进程数问题

https://cloud-atlas.readthedocs.io/zh_CN/latest/android/apps/android_12_background_limit_termux.html

在Termux中自动修改max_phantom_processes

打开Android设备的WiFi调试功能(Wireless debugging),并进行配对。

~/Android/android-sdk-tools/platform-tools/adb pair 127.0.0.1:${your_pair_port}
# 输入配对码

# 配对成功后
~/Android/android-sdk-tools/platform-tools/adb connect 127.0.0.1${your_connect_port}

# 连接成功后,查看当前系统配置
~/Android/android-sdk-tools/platform-tools/adb shell "/system/bin/dumpsys activity settings"

# 其中有一个max_phantom_processes=32,我们需要修改它
~/Android/android-sdk-tools/platform-tools/adb shell "device_config put activity_manager max_phantom_processes 32768"
~/Android/android-sdk-tools/platform-tools/adb shell "/system/bin/device_config set_sync_disabled_for_tests persistent"

# 查看修改是否成功
~/Android/android-sdk-tools/platform-tools/adb shell "/system/bin/dumpsys activity settings"

Termux自动连接ADB

因为是想用来写写Android的代码(强行生产力,不止爱奇艺),所以就有了这个需求,主要是为了自己方便

  1. 需要先安装nmap

    sudo apt install nmap -y
  2. 自动连接adb

    # 我喜欢把自定义脚本放在同一个文件夹中
    # mkdir ~/scripts
    
    # 编写
    nano ~/scripts/adb_magic_connection.sh

    写入以下代码

    #!/bin/bash
    # Author: https://www.alainlam.cn
    # 本脚本需要已经配对过的情况下
    
    ### 配置变量配置
    #
    # adb路径
    adb() {
        ~/Android/android-sdk-tools/platform-tools/adb "$@"
    }
    # 用于存放以往的端口
    adb_port_file=~/log/adb_port.txt
    # 用于端口号不存在或者失效时,扫描的端口范围
    # 我的平板端口号开的范围比较大,请适当调整
    port_range="30000-50000"
    #
    ######
    
    connect_to_ports() {
        local ports=("$@")
        for port in "${ports[@]}"; do
            # 尝试连接
            echo "adb connecting localhost:$port"
            adb_output=$(adb connect localhost:"$port" 2>&1)
            # 检查是否连接成功
            if [[ $adb_output =~ connected ]]; then
                echo "adb connected localhost:$port"
                # 修改max_phantom_processes
                echo "update max_phantom_processes to 32768"
                adb -s localhost:$port shell device_config put activity_manager max_phantom_processes 32768
                # 端口号写入文件中
                echo "$port" >$adb_port_file
                # 如果start-server非空的话,则一开始没有打开过adb,那么结束adb
                if [ $kill_adb -eq 1 ]; then
                    adb kill-server
                    echo "adb killed server"
                fi
                # 结束代码
                exit 0
            else
                echo "Failed to connect to port $port"
                # 避免在adb devices列出过多的设备
                adb disconnect localhost:"$port"
            fi
        done
        echo "Failed to connect to any port"
        # 如果start-server非空的话,则一开始没有打开过adb,那么结束adb
        if [ $kill_adb -eq 1 ]; then
            adb kill-server
            echo "adb killed server"
        fi
    }
    
    # 开启adb
    kill_adb=0
    if ! pgrep -x "adb" >/dev/null; then
        adb start-server
        kill_adb=1
    fi
    
    # 尝试连接以前的端口
    if [ -f "$adb_port_file" ]; then
        adb_port=$(cat "$adb_port_file")
    else
        echo "Port file $adb_port_file does not exist"
        directory=$(dirname "$adb_port_file")
        # 如果目录不存在,先创建目录
        if [ ! -d "$directory" ]; then
            mkdir -p "$directory"
        fi
    fi
    
    # 检查端口是否开启
    if [ -n "$adb_port" ]; then
        echo "pending the localhost:$adb_port"
        nmap_output=$(nmap -p "$adb_port" localhost)
        if [[ $nmap_output == *"$adb_port/tcp"*open* ]]; then
            echo "Port $adb_port is open"
            # 尝试连接
            connect_to_ports "$adb_port"
        else
            echo "Port $adb_port is closed"
        fi
    fi
    
    # 提示用户选择一种方式
    selected_port_method=""
    
    while [[ $selected_port_method != "1" && $selected_port_method != "2" && $selected_port_method != "3" ]]; do
        read -p "
    Please choose the method you want:
    
        1. Enter the special port(Manual)
        2. Use nmap to scan the ports(Slowly)
        3. Skip for now
    
    Your choice(1/2/3): " selected_port_method
    done
    
    if [[ $selected_port_method == "1" ]]; then
        read -p "Please enter a special port(1-65535)" enter_port
        echo "pending the localhost:$enter_port"
        connect_to_ports "$enter_port"
    fi
    
    if [[ $selected_port_method == "2" ]]; then
        # 如果端口已经无效或不存在,则扫描端口并保存到adb_test_ports中
        echo "pending the localhost:[$port_range]"
        nmap_output=$(nmap -p "$port_range" localhost)
        while IFS= read -r line; do
            if [[ $line =~ ^[0-9]+/tcp.*open.* ]]; then
                echo "$line"
                port=$(echo "$line" | awk -F/ '{print $1}')
                adb_test_ports+=("$port")
            fi
        done <<<"$nmap_output"
    
        # 尝试连接端口
        connect_to_ports "${adb_test_ports[@]}"
    fi
  3. 修改权限

    chmod 700 ~/scripts/adb_magic_connection.sh
  4. 后面在启动脚本中会调用这个脚本

  5. 至此,所有配置均已完成,那么我们可以开启桌面模式了

    # 先退出debian
    # ctrl+d 到termux的shell

启动桌面

# 开启pulseaudio服务
pulseaudio --start --load="module-native-protocol-tcp auth-ip-acl=127.0.0.1 auth-anonymous=1" --exit-idle-time=-1
# pacmd load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1 auth-anonymous=1

# 设置显示变量为0
export DISPLAY=:0

# 启动termux-x11并设置到:0显示器
termux-x11 :1 &
# 一些设备只输出带有光标的黑屏需要使用传统绘图选项,比如Galaxy S8+
# https://github.com/termux/termux-x11/blob/master/README.md#running-graphical-applications
# termux-x11 :0 -legacy-drawing &

# 启动VirGL服务
virgl_test_server_android &

# 进入debian系统
proot-distro login debian --user alain --shared-tmp

# 或者直接执行以下命令
# proot-distro login debian --user alain --shared-tmp -- bash -c "export DISPLAY=:1;PULSE_SERVER=tcp:127.0.0.1; dbus-launch --exit-with-session startxfce4"

如果使用proot-distro login debian --user alain --shared-tmp进入Debian时,我们仍然需要执行以下命令来启动桌面环境

export DISPLAY=:0
PULSE_SERVER=tcp:127.0.0.1
dbus-launch --exit-with-session startxfce4

Termux一键启动桌面

mkdir .shortcuts
nano .shortcuts/DebianX.sh

写入以下代码, 然后长按桌面添加新控件

#!/bin/bash
# Author: https://www.alainlam.cn

# 关闭所有xfce的进程
processes=$(pgrep -f xfce4)
for pid in $processes; do
    echo "killing $pid"
    kill $pid
done

# 关闭所有x11的进程
processes=$(pgrep -f com.termux.x11)
for pid in $processes; do
    echo "killing x11 server: $pid"
    kill $pid
done

# 关闭所有pulseaudio的进程
processes=$(pgrep -f pulseaudio)
for pid in $processes; do
    echo "killing pulseaudio: $pid"
    kill $pid
done

# 关闭所有 virgl renderer的进程
processes=$(pgrep -f virglrenderer-android)
for pid in $processes; do
    echo "killing virglrenderer-android: $pid"
    kill $pid
done

echo "Starting X11 server"
XDG_RUNTIME_DIR=$TMPDIR
termux-x11 :0 -ac &
sleep 3

echo "Starting pulseaudio server"
pulseaudio --start --load="module-native-protocol-tcp auth-ip-acl=127.0.0.1 auth-anonymous=1" --exit-idle-time=-1

echo "Starting Virgl Renderer"
virgl_test_server_android &

# 自动连接adb
adb_magic_connection='
script_path=~/scripts/adb_magic_connection.sh
if [ -f "$script_path" ]; then
    echo "ADB: Attempting to automatically connect to localhost(device)"
    bash "$script_path"
else
    echo "Skipped ADB connection"
fi
'
proot-distro login debian --shared-tmp --user alain -- bash -c "$adb_magic_connection"

# 跳转到Termux X11
am start --user 0 -n com.termux.x11/com.termux.x11.MainActivity

# 启动桌面环境
proot-distro login debian --user '"$normal_user_name"' --shared-tmp -- bash -c "export DISPLAY=:0 PULSE_SERVER=tcp:127.0.0.1; dbus-launch --exit-with-session startxfce4"
标签: Android IDEA termux
最后更新:2025年3月16日

Alain

看了我的文,就是我的人,点个赞再走成不成

点赞
< 上一篇
下一篇 >

文章评论

  • iPupil

    export ANDROID_SDK_HOME=$ANDROID_HOME
    这个环境变量因为容易歧义已经被废置了,不需要设置,否则会构建失败(摸索了快一天才发现是这里的问题 :lol: )

    2025年3月14日
    回复
    • Alain

      @iPupil 确实,但是我印象中某些CI环境中没有它又不行,不过你是对的,这里不需要ANDROID_SDK_HOME

      2025年3月15日
      回复
  • 取消回复

    文章目录
    • 开源工具
    • Termux系列软件安装包
      • 安装包
      • Termux初始化安装
    • Termux中安装proot-distro,并安装Debian系统
      • Debian安装浏览器等常用软件,并新增普通用户
      • Debian安装xfce4桌面环境,并解决中文乱码
    • Termux安装VSCode(Code-Server)
      • 安装VSCode(Code-Server)
    • Termux安装Android Studio
      • 安装JDK 17(Proot-distro中的Android Studio必须JDK17以上)
      • 安装Android SDK(Commandline-tools)
      • 配置Android环境变量
      • 安装Android Studio
      • Termux修复aapt2等编译工具问题
      • 修复NDK问题
      • 修复模拟器导致无法运行程序的问题
    • Android12以上修复Termux进程数问题
      • 在Termux中自动修改max_phantom_processes
    • Termux自动连接ADB
    • 启动桌面
      • Termux一键启动桌面

    COPYRIGHT © 2022 Alain's Blog. ALL RIGHTS RESERVED.

    Theme Kratos Made By Seaton Jiang