Android studio 呼叫盒app

一、权限文件

0.gradle切换国内源

复制代码
#Fri Nov 08 15:46:05 CST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https://mirrors.cloud.tencent.com/gradle/gradle-8.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

1.添加仅测试声明,针对vivo手机安装不上app

复制代码
android.injected.testOnly=false

2.添加弹窗块的代码

复制代码
    implementation("androidx.appcompat:appcompat:1.6.1")

3.申请使用网络权限

复制代码
    <!-- 申请网络权限 -->
    <uses-permission android:name="android.permission.INTERNET"/>

二、前端UI布局

1.activity_main.xml

复制代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 按钮和灯的布局 -->
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_centerInParent="true">

        <!-- 按钮1 -->
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="center_vertical"
            android:layout_marginBottom="16dp">

            <View
                android:id="@+id/light1"
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:layout_marginEnd="10dp"
                android:background="@android:color/darker_gray" />

            <Button
                android:id="@+id/button1"
                android:layout_width="150dp"
                android:layout_height="50dp"
                android:text="1"
                android:backgroundTint="@android:color/darker_gray"
                android:textColor="@android:color/white" />
        </LinearLayout>

        <!-- 按钮2 -->
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="center_vertical"
            android:layout_marginBottom="16dp">

            <View
                android:id="@+id/light2"
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:layout_marginEnd="10dp"
                android:background="@android:color/darker_gray" />

            <Button
                android:id="@+id/button2"
                android:layout_width="150dp"
                android:layout_height="50dp"
                android:text="2"
                android:backgroundTint="@android:color/darker_gray"
                android:textColor="@android:color/white" />
        </LinearLayout>

        <!-- 按钮3 -->
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="center_vertical"
            android:layout_marginBottom="16dp">

            <View
                android:id="@+id/light3"
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:layout_marginEnd="10dp"
                android:background="@android:color/darker_gray" />

            <Button
                android:id="@+id/button3"
                android:layout_width="150dp"
                android:layout_height="50dp"
                android:text="3"
                android:backgroundTint="@android:color/darker_gray"
                android:textColor="@android:color/white" />
        </LinearLayout>

        <!-- 按钮4 -->
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="center_vertical">

            <View
                android:id="@+id/light4"
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:layout_marginEnd="10dp"
                android:background="@android:color/darker_gray" />

            <Button
                android:id="@+id/button4"
                android:layout_width="150dp"
                android:layout_height="50dp"
                android:text="4"
                android:backgroundTint="@android:color/darker_gray"
                android:textColor="@android:color/white" />
        </LinearLayout>
    </LinearLayout>

    <!-- 设置按钮 -->
    <Button
        android:id="@+id/settingsButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="设置"
        android:backgroundTint="@android:color/darker_gray"
        android:textColor="@android:color/white"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="16dp" />
</RelativeLayout>

2.dialog_settings.xml

复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="16dp">

    <!-- 目标 IP -->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="目标 IP:" />
    <EditText
        android:id="@+id/targetIp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入目标 IP"
        android:inputType="text" />

    <!-- 目标端口 -->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="目标端口:"
        android:layout_marginTop="8dp" />
    <EditText
        android:id="@+id/targetPort"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入目标端口"
        android:inputType="number" />

    <!-- 本地端口 -->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="本地端口:"
        android:layout_marginTop="8dp" />
    <EditText
        android:id="@+id/localPort"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入本地端口"
        android:inputType="number" />
</LinearLayout>

三、后端文件

MainActivity.java

复制代码
package com.example.fl;

import android.app.AlertDialog;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class MainActivity extends AppCompatActivity {

    private String targetIp = "192.168.0.229"; // 默认目标 IP
    private int targetPort = 10000; // 默认目标端口
    private int localPort = 55555; // 默认本地端口49200-65535
    private DatagramSocket socket;

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

        // 从 SharedPreferences 中读取保存的设置
        SharedPreferences preferences = getSharedPreferences("UDPSettings", MODE_PRIVATE);
        targetIp = preferences.getString("targetIp", "192.168.0.229"); // 默认值
        targetPort = preferences.getInt("targetPort", 10000); // 默认值
        localPort = preferences.getInt("localPort", 55555); // 默认值

        initializeSocket();

        setupButtonAndLight(R.id.button1, R.id.light1, "1");
        setupButtonAndLight(R.id.button2, R.id.light2, "2");
        setupButtonAndLight(R.id.button3, R.id.light3, "3");
        setupButtonAndLight(R.id.button4, R.id.light4, "4");

        Button settingsButton = findViewById(R.id.settingsButton);
        settingsButton.setOnClickListener(v -> openSettingsDialog());
    }


    private void initializeSocket() {
        try {
            if (socket != null && !socket.isClosed()) {
                socket.close();
            }
            socket = new DatagramSocket(localPort);
            new Thread(this::receiveUDPMessage).start();
        } catch (Exception e) {
            e.printStackTrace();
            Toast.makeText(this, "Socket 初始化失败,请检查本地端口设置", Toast.LENGTH_SHORT).show();
        }
    }

    private void setupButtonAndLight(int buttonId, int lightId, String message) {
        Button button = findViewById(buttonId);
        View light = findViewById(lightId);

        button.setOnClickListener(v -> {
            sendUDPMessage(message, success -> {
                if (success) {
                    runOnUiThread(() -> light.setBackgroundColor(getResources().getColor(android.R.color.holo_green_light)));
                } else {
                    runOnUiThread(() -> Toast.makeText(this, "发送失败", Toast.LENGTH_SHORT).show());
                }
            });
        });
    }

    private void sendUDPMessage(String message, UDPResponseCallback callback) {
        new Thread(() -> {
            boolean success = false;
            try {
                InetAddress address = InetAddress.getByName(targetIp);
                DatagramPacket packet = new DatagramPacket(message.getBytes(), message.length(), address, targetPort);
                socket.send(packet);
                success = true;
            } catch (Exception e) {
                e.printStackTrace();
            }
            callback.onResponse(success);
        }).start();
    }

    private void receiveUDPMessage() {
        byte[] buffer = new byte[1024];
        while (true) {
            try {
                DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
                socket.receive(packet);
                String received = new String(packet.getData(), 0, packet.getLength());
                runOnUiThread(() -> handleReceivedMessage(received));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void handleReceivedMessage(String message) {
        int lightId;
        switch (message) {
            case "1":
                lightId = R.id.light1;
                break;
            case "2":
                lightId = R.id.light2;
                break;
            case "3":
                lightId = R.id.light3;
                break;
            case "4":
                lightId = R.id.light4;
                break;
            default:
                return;
        }

        View light = findViewById(lightId);
        light.setBackgroundColor(getResources().getColor(android.R.color.darker_gray));
    }

    private void openSettingsDialog() {
        View dialogView = LayoutInflater.from(this).inflate(R.layout.dialog_settings, null);
        EditText ipInput = dialogView.findViewById(R.id.targetIp);
        EditText portInput = dialogView.findViewById(R.id.targetPort);
        EditText localPortInput = dialogView.findViewById(R.id.localPort);

        // 获取 SharedPreferences 保存的数据
        SharedPreferences preferences = getSharedPreferences("UDPSettings", MODE_PRIVATE);
        ipInput.setText(preferences.getString("targetIp", targetIp));
        portInput.setText(String.valueOf(preferences.getInt("targetPort", targetPort)));
        localPortInput.setText(String.valueOf(preferences.getInt("localPort", localPort)));

        new AlertDialog.Builder(this)
                .setTitle("设置目标和本地端口")
                .setView(dialogView)
                .setPositiveButton("保存", (dialog, which) -> {
                    targetIp = ipInput.getText().toString();
                    targetPort = Integer.parseInt(portInput.getText().toString());
                    localPort = Integer.parseInt(localPortInput.getText().toString());

                    // 保存设置到 SharedPreferences
                    SharedPreferences.Editor editor = preferences.edit();
                    editor.putString("targetIp", targetIp);
                    editor.putInt("targetPort", targetPort);
                    editor.putInt("localPort", localPort);
                    editor.apply();

                    initializeSocket(); // 更新本地端口后重新初始化 Socket
                    Toast.makeText(this, "设置已保存", Toast.LENGTH_SHORT).show();
                })
                .setNegativeButton("取消", null)
                .show();
    }


    // 定义回调接口
    private interface UDPResponseCallback {
        void onResponse(boolean success);
    }
}

四、实现效果

app按下1234 绿色led亮 目标设备收到数据

回传本地IP和端口 1

led1 灯灭

链接: https://pan.baidu.com/s/1x46I-dhMG_2mRchokZ0xiA?pwd=ktam 提取码: ktam

相关推荐
夏沫琅琊2 小时前
Android 各类日志全面解析(含特点、分析方法、实战案例)
android
程序员JerrySUN2 小时前
OP-TEE + YOLOv8:从“加密权重”到“内存中解密并推理”的完整实战记录
android·java·开发语言·redis·yolo·架构
TeleostNaCl3 小时前
Android | 启用 TextView 跑马灯效果的方法
android·经验分享·android runtime
TheNextByte14 小时前
Android USB文件传输无法使用?5种解决方法
android
怪力左手4 小时前
vscode扩展离线下载
ide·vscode·编辑器
quanyechacsdn5 小时前
Android Studio创建库文件用jitpack构建后使用implementation方式引用
android·ide·kotlin·android studio·implementation·android 库文件·使用jitpack
程序员陆业聪6 小时前
聊聊2026年Android开发会是什么样
android
编程大师哥6 小时前
Android分层
android
larance7 小时前
jupyter 服务端扩展开发
ide·python·jupyter
极客小云8 小时前
【深入理解 Android 中的 build.gradle 文件】
android·安卓·安全架构·安全性测试