【UE5】如何开发安卓项目的udp客户端

1关于如何打包安卓项目这里就不赘述了

2代码举例。最重要的就是这两句`

cpp 复制代码
#if PLATFORM_ANDROID
#endif

#if PLATFORM_WINDOWS
#endif

全部代码如下:

Button_Sheng.h:

cpp 复制代码
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"

#include "Components/Button.h"
#include "Components/TextBlock.h"

#include "Button_Sheng.generated.h"
#if PLATFORM_ANDROID
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <unistd.h>  
#include <arpa/inet.h>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <pthread.h>  
#endif

/**
 * 
 */
UCLASS()
class CCEC_CLIENT_0113_API UButton_Sheng : public UUserWidget
{
	GENERATED_BODY()

public:
    // 声明按钮和文本块
    UPROPERTY(meta = (BindWidget))
    UButton* MyButton;

    UPROPERTY(meta = (BindWidget))
    UTextBlock* MyTextBlock;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Custom")
    int Code;

    
    // 移植过来的函数声明
    UFUNCTION(BlueprintCallable, Category = "aaaaaa")
    void Sheng(FString Message);
protected:
    // 构造函数
    virtual void NativeConstruct() override;


public:
    // 动态创建 Widget 的函数
    UFUNCTION(BlueprintCallable, Category = "Widget")
    void CreateDynamicWidget(int32 WidgetID);

    // 动态创建 Widget 的函数(基于 FString)
    UFUNCTION(BlueprintCallable, Category = "Widget")
    void CreateDynamicWidgetByName(const FString& WidgetName);

protected:
    // 父容器,用于存放动态创建的 Widget
    //UPROPERTY(meta = (BindWidget))
    //class UPanelWidget* ParentContainer;
};

Button_Sheng.cpp:

cpp 复制代码
#include "Button_Sheng.h"
#include "Components/WidgetComponent.h"
#include <iostream>  

#include "Blueprint/WidgetTree.h"
#include "Components/PanelWidget.h"
#include "UObject/ConstructorHelpers.h"

#if PLATFORM_ANDROID
#define BROADCAST_PORT 8888  
#define BROADCAST_PORT2 8889  
#define BROADCAST_PORT3 8887 
#define BROADCAST_MESSAGE1 "1" 
#define BROADCAST_MESSAGE2 "2" 
#define BROADCAST_MESSAGE3 "3" 
#define BROADCAST_MESSAGE42 "42"

void* send_broadcast13(void* arg) {
    int sockfd;
    struct sockaddr_in broadcast_addr;
    const char* message = static_cast<const char*>(arg);
    //char* message = (char*)arg;
    ssize_t bytes_sent;

    // 创建UDP套接字  
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket creation failed");
        pthread_exit(NULL);
    }
    // 允许广播  
    int broadcast_enable = 1;
    if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast_enable, sizeof(broadcast_enable)) < 0) {
        perror("setsockopt(SO_BROADCAST) failed");
        close(sockfd);
        pthread_exit(NULL);
    }

    // 设置广播地址  
    memset(&broadcast_addr, 0, sizeof(broadcast_addr));
    broadcast_addr.sin_family = AF_INET;
    broadcast_addr.sin_addr.s_addr = inet_addr("255.255.255.255"); // 局域网广播地址  
    broadcast_addr.sin_port = htons(BROADCAST_PORT);

    // 发送广播消息  
    bytes_sent = sendto(sockfd, message, strlen(message), 0, (struct sockaddr*)&broadcast_addr, sizeof(broadcast_addr));
    if (bytes_sent < 0) {
        perror("sendto failed");
    }
    else {
        printf("Broadcast message sent: %s\n", message);
    }

    // 关闭套接字  
    close(sockfd);

    pthread_exit(NULL);
}
void* send_broadcast14(void* arg) {
    int sockfd;
    struct sockaddr_in broadcast_addr;
    char* message = (char*)arg;
    ssize_t bytes_sent;

    // 创建UDP套接字  
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket creation failed");
        pthread_exit(NULL);
    }
    // 允许广播  
    int broadcast_enable = 1;
    if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast_enable, sizeof(broadcast_enable)) < 0) {
        perror("setsockopt(SO_BROADCAST) failed");
        close(sockfd);
        pthread_exit(NULL);
    }

    // 设置广播地址  
    memset(&broadcast_addr, 0, sizeof(broadcast_addr));
    broadcast_addr.sin_family = AF_INET;
    broadcast_addr.sin_addr.s_addr = inet_addr("255.255.255.255"); // 局域网广播地址  
    broadcast_addr.sin_port = htons(BROADCAST_PORT2);

    // 发送广播消息  
    bytes_sent = sendto(sockfd, message, strlen(message), 0, (struct sockaddr*)&broadcast_addr, sizeof(broadcast_addr));
    if (bytes_sent < 0) {
        perror("sendto failed");
    }
    else {
        printf("Broadcast message sent: %s\n", message);
    }

    // 关闭套接字  
    close(sockfd);

    pthread_exit(NULL);
}

void* send_broadcast15(void* arg) {
    int sockfd;
    struct sockaddr_in broadcast_addr;
    char* message = (char*)arg;
    ssize_t bytes_sent;
    const char* message1 = "1";
    const char* message2 = "2";
    // 创建UDP套接字  
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket creation failed");
        pthread_exit(NULL);
    }
    // 允许广播  
    int broadcast_enable = 1;
    if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast_enable, sizeof(broadcast_enable)) < 0) {
        perror("setsockopt(SO_BROADCAST) failed");
        close(sockfd);
        pthread_exit(NULL);
    }

    // 设置广播地址  
    memset(&broadcast_addr, 0, sizeof(broadcast_addr));
    broadcast_addr.sin_family = AF_INET;
    broadcast_addr.sin_addr.s_addr = inet_addr("255.255.255.255"); // 局域网广播地址  
    broadcast_addr.sin_port = htons(BROADCAST_PORT2);

    sleep(6);
    // 发送广播消息  
    bytes_sent = sendto(sockfd, message2, strlen(message2), 0, (struct sockaddr*)&broadcast_addr, sizeof(broadcast_addr));

    sleep(6);
    // 发送广播消息  
    bytes_sent = sendto(sockfd, message1, strlen(message1), 0, (struct sockaddr*)&broadcast_addr, sizeof(broadcast_addr));

    // 关闭套接字  
    close(sockfd);

    pthread_exit(NULL);
}
void* send_broadcast16(void* arg) {
    int sockfd;
    struct sockaddr_in broadcast_addr;
    char* message = (char*)arg;
    ssize_t bytes_sent;

    // 创建UDP套接字  
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket creation failed");
        pthread_exit(NULL);
    }
    // 允许广播  
    int broadcast_enable = 1;
    if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast_enable, sizeof(broadcast_enable)) < 0) {
        perror("setsockopt(SO_BROADCAST) failed");
        close(sockfd);
        pthread_exit(NULL);
    }

    // 设置广播地址  
    memset(&broadcast_addr, 0, sizeof(broadcast_addr));
    broadcast_addr.sin_family = AF_INET;
    broadcast_addr.sin_addr.s_addr = inet_addr("255.255.255.255"); // 局域网广播地址  
    broadcast_addr.sin_port = htons(BROADCAST_PORT3);//就在这改!!!!!!!!!!!!

    // 发送广播消息  
    bytes_sent = sendto(sockfd, message, strlen(message), 0, (struct sockaddr*)&broadcast_addr, sizeof(broadcast_addr));
    if (bytes_sent < 0) {
        perror("sendto failed");
    }
    else {
        printf("Broadcast message sent: %s\n", message);
    }

    // 关闭套接字  
    close(sockfd);

    pthread_exit(NULL);
}
#endif

#if PLATFORM_ANDROID
void UButton_Sheng::Sheng(FString Message)
{
    // 为 Message 分配足够的空间,包括 null 终止符
    int32 Length = Message.Len() + 1;
    char* MessageCStr = new char[Length];
    FMemory::Memcpy(MessageCStr, TCHAR_TO_UTF8(*Message), Length);

    pthread_t thread1, thread2, thread3;
    // 创建线程来发送第一个广播消息  
    if (pthread_create(&thread1, NULL, send_broadcast13, (void*)MessageCStr) != 0) {//调用8888的函数,传入1
        perror("pthread_create for first message failed");
        exit(EXIT_FAILURE);
    }
    // 注意:为每个 pthread_create 调用复制新的字符串或使用其他同步机制来共享同一个字符串
    // 这里为了简化,我们为每个线程都复制了一个新字符串(这不是最高效的方法,但避免了线程安全问题)
    char* MessageCStr2 = new char[Length];
    FMemory::Memcpy(MessageCStr2, TCHAR_TO_UTF8(*Message), Length);

    // 创建线程来发送第二个广播消息  
    if (pthread_create(&thread2, NULL, send_broadcast14, (void*)MessageCStr2) != 0) {//调用8889的第一个函数,传入1
        perror("pthread_create for second message failed");
        // 注意:这里应该加入代码来取消或等待第一个线程,以避免资源泄露  
        // 但为了简单起见,我们直接退出程序(在实际应用中,这是不推荐的)  
        exit(EXIT_FAILURE);
    }
    char* MessageCStr3 = new char[Length];
    FMemory::Memcpy(MessageCStr3, TCHAR_TO_UTF8(*Message), Length);

    // 创建线程来发送第二个广播消息  
    if (pthread_create(&thread3, NULL, send_broadcast16, (void*)MessageCStr3) != 0) {//调用8889的第一个函数,传入1
        perror("pthread_create for second message failed");
        // 注意:这里应该加入代码来取消或等待第一个线程,以避免资源泄露  
        // 但为了简单起见,我们直接退出程序(在实际应用中,这是不推荐的)  
        exit(EXIT_FAILURE);
    }
    // 等待两个线程完成  
    if (pthread_join(thread1, NULL) != 0) {
        perror("pthread_join for first message failed");
    }
    if (pthread_join(thread2, NULL) != 0) {
        perror("pthread_join for second message failed");
    }
    if (pthread_join(thread3, NULL) != 0) {
        perror("pthread_join for first message failed");
    }
    // 释放内存
    delete[] MessageCStr;
    delete[] MessageCStr2;
    delete[] MessageCStr3;
}
#endif

#if PLATFORM_WINDOWS
void UButton_Sheng::Sheng(FString Message)
{
    UE_LOG(LogTemp, Error, TEXT(" %s"), *Message);
}
#endif

void UButton_Sheng::NativeConstruct()
{
}

void UButton_Sheng::CreateDynamicWidget(int32 WidgetID)
{
    // 根据 WidgetID 拼接资源路径
    FString WidgetPath = FString::Printf(TEXT("/Game/widget/Widget_%d.Widget_%d_C"), WidgetID, WidgetID);

    // 加载 Widget Class
    TSubclassOf<UUserWidget> WidgetClass = LoadClass<UUserWidget>(nullptr, *WidgetPath);
    if (WidgetClass)
    {
        // 创建 Widget 实例
        UUserWidget* DynamicWidget = CreateWidget<UUserWidget>(GetWorld(), WidgetClass);
        if (DynamicWidget)
        {
            DynamicWidget->AddToViewport();
            UE_LOG(LogTemp, Log, TEXT("Widget %d created and added to container!"), WidgetID);
        }
    }
    else
    {
        UE_LOG(LogTemp, Error, TEXT("Failed to load Widget Class for ID: %d"), WidgetID);
    }
}

void UButton_Sheng::CreateDynamicWidgetByName(const FString& WidgetName)
{
    // 根据 WidgetName 拼接资源路径
    FString WidgetPath = FString::Printf(TEXT("/Game/UI/%s.%s_C"), *WidgetName, *WidgetName);

    // 加载 Widget Class
    TSubclassOf<UUserWidget> WidgetClass = LoadClass<UUserWidget>(nullptr, *WidgetPath);
    if (WidgetClass)
    {
        // 创建 Widget 实例
        UUserWidget* DynamicWidget = CreateWidget<UUserWidget>(GetWorld(), WidgetClass);
        if (DynamicWidget )
        {
          
        }
    }
    else
    {
        UE_LOG(LogTemp, Error, TEXT("Failed to load Widget Class for Name: %s"), *WidgetName);
    }
}
相关推荐
千里马学框架3 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台3 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone3 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc3 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo3 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077003 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼3 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone3 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen3 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone3 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui