1. 搭建QNX与Android融合开发环境

搭建QNX与Android融合开发环境 学习卡片

任务说明

本案例目标是在虚拟机中完成QNX与Android融合开发的基础环境搭建:安装QNX SDP(Software Development Platform)与Android Studio,配置用于QNX侧开发的交叉编译工具链,并验证宿主机与两个目标环境之间的基本通信能力。完成本案例后,你将获得一个可编译QNX原生程序、可构建Android APK、且两者能通过TCP/IP进行通信的开发基础环境。

环境与依赖

  • 宿主机:Ubuntu 20.04/22.04 x86_64,建议分配8GB以上内存、100GB磁盘
  • 虚拟化平台:VMware Workstation 16+ 或 VirtualBox 6.1+
  • QNX SDP 7.0:从BlackBerry QNX官网获取(需注册),或使用QNX 7.0 Evaluation Image
  • Android Studio:Arctic Fox或更新版本,包含Android SDK 30+
  • 交叉编译工具链:QNX SDP自带的qcc(基于GCC的QNX编译器),以及Android NDK r21+(用于JNI层交叉编译)

实施步骤

1. 虚拟机与QNX SDP安装

在VMware中创建虚拟机,选择"QNX 7.x"客户机类型(若列表无此项,选"Other Linux 5.x"亦可)。挂载QNX SDP安装ISO,启动后按提示完成安装。安装完成后,确认QNX系统可正常启动并获取IP地址:

ifconfig -a   # 确认网卡有IP,如 192.168.1.100

2. 宿主机安装QNX SDP Host侧工具

在Ubuntu宿主机上安装QNX SDP的Host开发包(通常为qnx-sdp-host-linux.tar.gz),解压后设置环境变量:

tar -xzf qnx-sdp-host-linux.tar.gz -C ~/qnx
# 将以下内容加入 ~/.bashrc
export QNX_HOST=~/qnx/host/linux/x86_64
export QNX_TARGET=~/qnx/target/qnx7
export PATH=$QNX_HOST/usr/bin:$PATH

3. 安装Android Studio与NDK

下载Android Studio安装包,解压到/opt/android-studio并启动。通过SDK Manager安装Android SDK Platform 30+和NDK r21+。确认NDK路径(如~/Android/Sdk/ndk/21.4.7075529)。

4. 验证QNX交叉编译工具链

编写一个最小QNX程序并交叉编译,验证工具链可用:

# hello_qnx.c
#include <stdio.h>
int main() { printf("QNX toolchain OK\n"); return 0; }
qcc -Vgcc_ntox86_64 hello_qnx.c -o hello_qnx
file hello_qnx   # 应输出 ELF 64-bit LSB executable, x86-64

5. 配置QNX与Android通信基础环境

在QNX虚拟机中启用TCP/IP并设置静态IP(或使用DHCP),在宿主机Android模拟器中确认网络连通。以下代码实现一个最小TCP通信验证——QNX侧作为服务端监听端口,Android侧作为客户端连接并发送消息:

关键完整代码

// ============ QNX侧:tcp_server.c ============
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

#define PORT 54321

int main() {
    int server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd < 0) { perror("socket"); return 1; }

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(PORT);

    if (bind(server_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
        perror("bind"); return 1;
    }
    listen(server_fd, 1);
    printf("QNX server listening on port %d\n", PORT);

    int client_fd = accept(server_fd, NULL, NULL);
    if (client_fd < 0) { perror("accept"); return 1; }

    char buf[128];
    int n = read(client_fd, buf, sizeof(buf) - 1);
    if (n > 0) {
        buf[n] = '\0';
        printf("Received: %s\n", buf);
        write(client_fd, "ACK from QNX", 13);
    }
    close(client_fd);
    close(server_fd);
    return 0;
}
// ============ Android侧:MainActivity.java(关键部分) ============
// 在AndroidManifest.xml中添加 <uses-permission android:name="android.permission.INTERNET"/>
// 在模拟器启动参数中添加 -dns-server 8.8.8.8 以解决DNS问题

public class MainActivity extends AppCompatActivity {
    private static final String QNX_HOST = "192.168.1.100"; // QNX虚拟机IP
    private static final int QNX_PORT = 54321;

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

        new Thread(() -> {
            try {
                Socket socket = new Socket(QNX_HOST, QNX_PORT);
                OutputStream out = socket.getOutputStream();
                out.write("Hello from Android".getBytes());
                out.flush();

                InputStream in = socket.getInputStream();
                byte[] buf = new byte[128];
                int n = in.read(buf);
                if (n > 0) {
                    String response = new String(buf, 0, n);
                    runOnUiThread(() -> {
                        TextView tv = findViewById(R.id.tv_status);
                        tv.setText("QNX回复: " + response);
                    });
                }
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

运行与验证

  1. QNX侧编译与运行:在宿主机执行qcc -Vgcc_ntox86_64 tcp_server.c -o tcp_server,将生成的tcp_server拷贝到QNX虚拟机(通过scp或共享目录),在QNX shell中运行./tcp_server,看到监听日志即成功。
  2. Android侧构建:在Android Studio中创建新项目,将上述代码填入MainActivity,添加INTERNET权限,连接模拟器(使用-network-speed full启动),点击Run。
  3. 通信验证:确保QNX虚拟机与Android模拟器网络互通(互相ping通)。运行Android应用后,观察QNX侧终端输出Received: Hello from Android,Android界面显示QNX回复: ACK from QNX,即表示通信链路建立成功。

通过条件:QNX侧交叉编译产物可在QNX系统正常运行;Android应用可成功连接QNX服务端并完成双向消息收发。若网络不通,优先检查虚拟机网络模式(建议使用桥接模式)和防火墙设置。