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

相关推荐
麻花疼不疼10 分钟前
php 使用mqtt
android·开发语言·php
@解忧杂货铺1 小时前
Android和IOS的区别
android·ios·cocoa
魑魅魍魉95272 小时前
Android 超大图预览 防止OOM
android
少说多做3432 小时前
Android 网络请求(一)初识HTTP网络通信
android·网络
sunly_2 小时前
Flutter:photo_view图片预览功能
android·javascript·flutter
Random_index2 小时前
#开发环境篇:vscode里面登录已同步设置的提示1怎么取消
ide·vscode·编辑器
叮当喵是mao4 小时前
python基础知识(七)——写入excel
android·python·excel
踏雪羽翼4 小时前
android 使用MediaPlayer实现音乐播放--获取音乐数据
android·开发语言·获取音乐数据
栽树先生~6 小时前
解决IntelliJ IDEA的Plugins无法访问Marketplace去下载插件
java·ide·intellij-idea
老码沉思录7 小时前
Android开发实战班 - 数据持久化 - Room 数据库应用
android·jvm·数据库