From f67f485172fcc597cd1d000a96a30bef10940a11 Mon Sep 17 00:00:00 2001 From: zhenghaoyuan20 <735827001@qq.com> Date: Mon, 26 Jun 2023 10:57:41 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=94=B5=E9=87=8F=E9=A2=84?= =?UTF-8?q?=E8=AD=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/sixaunyi/VideoActivity.java | 639 ++++++++++++++++++ 1 file changed, 639 insertions(+) create mode 100644 src/sixaunyi/app/src/main/java/com/example/sixaunyi/VideoActivity.java diff --git a/src/sixaunyi/app/src/main/java/com/example/sixaunyi/VideoActivity.java b/src/sixaunyi/app/src/main/java/com/example/sixaunyi/VideoActivity.java new file mode 100644 index 0000000..0ecce42 --- /dev/null +++ b/src/sixaunyi/app/src/main/java/com/example/sixaunyi/VideoActivity.java @@ -0,0 +1,639 @@ +package com.example.sixaunyi; + +import static androidx.constraintlayout.motion.utils.Oscillator.TAG; +import android.app.AlertDialog; +import android.content.DialogInterface; +import androidx.appcompat.app.AppCompatActivity; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.RectF; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.provider.ContactsContract; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; +import android.widget.Button; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.InetAddress; +import java.net.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import android.os.Bundle; + +public class VideoActivity extends AppCompatActivity { + private final static String SEND_to_IP = "192.168.39.47"; //填写接收方IP + private final static String Recieve_IP = "192.168.39.47";//填服务器IP,与send_to_IP为同一个 + private final static int SEND_PORT = 8888; //发送端口号 + private final static int RECEIVE_PORT = 9999; //接收端口号 + private static boolean listenStatus = true; //接收线程的循环标识 + private byte[] buf; + static Bitmap bp; + private DatagramSocket reveSocket; + private DatagramSocket sendSocket; + private static InetAddress serverAddr; + private SendHandler sendHandler = new SendHandler(); + private ReceiveHandler receiveHandler = new ReceiveHandler(); + private Button Trans_to_Detect; + private ImageView imgShow; + private Button btn; + private ImageButton Forward_btn; + private ImageButton Back_btn; + private ImageButton Left_btn; + private ImageButton Right_btn; + private ImageButton Down_btn; + private ImageButton Up_btn; + private ImageButton TurnLeft_btn; + private ImageButton TurnRight_btn; + private ImageButton Setting_btn; + private ImageButton TakeOff_btn; + private ImageButton Landing_btn; + private TextView battery_warning; + private String mangle; + private float mdistance; + // 创建一个可缓存的线程池 + private ExecutorService mThreadPool = Executors.newCachedThreadPool(); + private UdpDataThread warning_thread; + //ReceiveData()显示到imageView + //manager部分:打开线程,接收 + //model部分:发送视频流 + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_control); + imgShow = findViewById(R.id.imageView); + Forward_btn = findViewById(R.id.forward_button); + Back_btn = findViewById(R.id.backward_button); + Left_btn = findViewById(R.id.left_button); + Right_btn = findViewById(R.id.right_button); + Down_btn = findViewById(R.id.down_button); + Up_btn = findViewById(R.id.up_button); + TurnLeft_btn = findViewById(R.id.rotate_left_button); + Landing_btn = findViewById(R.id.landing_button); + TurnRight_btn = findViewById(R.id.rotate_right_button); + TakeOff_btn = findViewById(R.id.takeoff_button); + battery_warning =findViewById(R.id.warning); + battery_warning.setTextColor(Color.RED); + Animation anim = new AlphaAnimation(0.0f, 1.0f); + anim.setDuration(500); // 闪烁时间间隔 + anim.setStartOffset(20); + anim.setRepeatMode(Animation.REVERSE); + anim.setRepeatCount(Animation.INFINITE); + battery_warning.startAnimation(anim); + TakeOff_btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + try { + sendCommand("TAKEOFF"); + } catch (UnknownHostException e) { + throw new RuntimeException(e); + } + Log.i(TAG, "onClick: TTTTTTTTTTTTTTakeoff"); + } + }); + Landing_btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ReceiveHandler receiveHandler = new ReceiveHandler(); + UdpReceiveThread StreamThread = new UdpReceiveThread(Recieve_IP,RECEIVE_PORT,receiveHandler); + + try { + StreamThread.startListen(); + StreamThread.start(); + } catch (SocketException | UnknownHostException e) { + e.printStackTrace(); + } + } + + }); + Setting_btn = findViewById(R.id.setting_button); + Button_Init(); + Intent i = getIntent(); + mdistance = i.getFloatExtra("Distance",0); + mangle = i.getStringExtra("Angle"); + warning_thread = new UdpDataThread(); + warning_thread.start(); + + } + + private void Button_Init(){ + Forward_btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + try { + sendCommand("FORWARD"); + } catch (UnknownHostException e) { + throw new RuntimeException(e); + } + Log.i(TAG, "onClick: FFFFFFFForward"); + } + }); + Back_btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + try { + sendCommand("BACKWORD"); + } catch (UnknownHostException e) { + throw new RuntimeException(e); + } + Log.i(TAG, "onClick: BBBBBBBBackward"); + } + }); + Left_btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + try { + sendCommand("LEFT"); + } catch (UnknownHostException e) { + throw new RuntimeException(e); + } + Log.i(TAG, "onClick: LLLLLLLLLLLLeft"); + } + }); + Right_btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + try { + sendCommand("RIGHT"); + } catch (UnknownHostException e) { + throw new RuntimeException(e); + } + Log.i(TAG, "onClick: RRRRRRRRRRight"); + } + }); + Down_btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + try { + sendCommand("DOWN"); + } catch (UnknownHostException e) { + throw new RuntimeException(e); + } + Log.i(TAG, "onClick: DDDDDDDDDown"); + } + }); + Up_btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + try { + sendCommand("UP"); + } catch (UnknownHostException e) { + throw new RuntimeException(e); + } + Log.i(TAG, "onClick: UUUUUUUUUUUUUUp"); + } + }); + TurnLeft_btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + try { + sendCommand("TURN_LEFT"); + } catch (UnknownHostException e) { + throw new RuntimeException(e); + } + Log.i(TAG, "onClick: TTTTTTTTTurnLLLLLLLLLLeft"); + } + }); + TurnRight_btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + try { + sendCommand("TURN_RIGHT"); + } catch (UnknownHostException e) { + throw new RuntimeException(e); + } + Log.i(TAG, "onClick: TTTTTTTTTTTTurnRRRRRRRRRRight"); + } + }); + Setting_btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(VideoActivity.this, SettingActivity.class); + startActivity(intent); + } + }); + } + public class UdpDataThread extends Thread { + private DatagramSocket socket; + private boolean running; + private byte[] buffer; + private static final int BUFFER_SIZE = 1024; // 设置接收缓冲区大小 + + public UdpDataThread() { + buffer = new byte[BUFFER_SIZE]; + } + + @Override + public void run() { + running = true; + + try { + socket = new DatagramSocket(6666); // 设置接收端口号 + while (running) { + DatagramPacket packet = new DatagramPacket(buffer, buffer.length); + socket.receive(packet); + String receivedData = new String(packet.getData(), 0, packet.getLength()); + if (receivedData.equals("电量低于10%")) { + battery_warning.setText(receivedData);}else{ + battery_warning.setText(""); + } + System.out.println("接收到数据:" + receivedData); + // 在这里处理收到的数据,可以根据实际需求进行解析或其他操作 + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (socket != null) { + socket.close(); + } + } + } + + public void stopThread() { + running = false; + } + } + + + + class ReceiveHandler extends Handler{ + @Override + public void handleMessage(Message msg) { + if (msg.what == 1) { + runOnUiThread(new Runnable() { + @Override + public void run() { + imgShow.setImageBitmap(bp); + } + }); + } + } + } + + class SendHandler extends Handler { + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + } + } + + /* + * UDP数据接受线程 + * */ + public class UdpReceiveThread extends Thread { + private DatagramSocket reveSocket; + private String Recieve_IP; + private int RECEIVE_PORT; + private Handler receiveHandler; + + public UdpReceiveThread(String ip, int port, Handler handler) { + this.Recieve_IP = ip; + this.RECEIVE_PORT = port; + this.receiveHandler = handler; + } + + public void startListen() throws SocketException, UnknownHostException { + reveSocket = new DatagramSocket(RECEIVE_PORT); + } + + public void stopListen() { + if (reveSocket != null && !reveSocket.isClosed()) { + listenStatus = false; + //reveSocket.close(); + } + } + + @Override + public void run() { + try { + InetAddress serverAddr = InetAddress.getByName(Recieve_IP); + while (listenStatus) { + byte[] inBuf = new byte[1024]; + DatagramPacket inPacket = new DatagramPacket(inBuf, inBuf.length); + reveSocket.receive(inPacket); + + if (!inPacket.getAddress().equals(serverAddr)) { + throw new IOException("未知名的报文"); + } + + ByteArrayInputStream in = new ByteArrayInputStream(inPacket.getData()); + receiveHandler.sendEmptyMessage(1); + bp = BitmapFactory.decodeStream(in); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /* + * UDP数据发送线程,Runnable方法 + * */ + class SendRunnable implements Runnable { + byte[] mData; + InetAddress mAddress; + int mPort; + + public SendRunnable(byte[] data, InetAddress address, int port) { + mData = data; + mAddress = address; + mPort = port; + } + + @Override + public void run() { + try { + // 创建发送数据报文 + DatagramPacket packet = new DatagramPacket(mData, mData.length, mAddress, mPort); + // 创建 DatagramSocket 对象并发送数据报文 + DatagramSocket socket = new DatagramSocket(); + socket.send(packet); + + // 关闭 DatagramSocket 对象 + socket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /*封装函数*/ + private void sendCommand(String str) throws UnknownHostException { + byte[] sendData = str.getBytes(); + InetAddress address = InetAddress.getByName(SEND_to_IP); + SendRunnable sendRunnable1 = new SendRunnable(sendData, address, SEND_PORT); + mThreadPool.execute(sendRunnable1); + } + /* + * UDP数据发送线程 + * */ + public static class UdpSendThread extends Thread { + + private InetAddress sendToIP; // 目标 IP 地址 + private int sendPort; // 目标端口号 + private byte[] sendData; // 要发送的数据 + + public UdpSendThread(InetAddress sendToIP, int sendPort, byte[] sendData) { + this.sendToIP = sendToIP; + this.sendPort = sendPort; + this.sendData = sendData; + } + + @Override + public void run() { + try { + DatagramSocket sendSocket = new DatagramSocket(); // 创建一个新的 DatagramSocket 对象 + DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, sendToIP, sendPort); // 将要发送的数据打包成一个 DatagramPacket 对象 + sendSocket.send(sendPacket); // 发送 DatagramPacket + sendSocket.close(); // 发送完毕后关闭 DatagramSocket + } catch (Exception e) { + e.printStackTrace(); + } + } + + } + //初始化UDP发送线程 +// private static void sendCommand(String Sendstr) throws UnknownHostException { +// InetAddress sendIP = InetAddress.getByName(SEND_to_IP); // 目标 IP 地址 +// int sendPort = 8888; // 目标端口号 +// byte[] sendData = Sendstr.getBytes(); // 要发送的数据 +// UdpSendThread sendCommandThread = new UdpSendThread(sendIP, sendPort, sendData); // 创建新的线程对象 +// sendCommandThread.start(); // 启动线程发送数据 +// } + + + + + +//设置按钮 +// public void showDialog(View view) { +// Dialog dialog = new Dialog(VideoActivity.this); +// dialog.setContentView(R.layout.dialog_takeoff); +// +// SlideUnlockView slideUnlockView = (SlideUnlockView) dialog.findViewById(R.id.slide_unlock_view); +// slideUnlockView.setOnUnlockListener(new SlideUnlockView.OnUnlockListener() { +// @Override +// public void onUnlock() { +// // 在用户滑动解锁后执行操作 +//// try { +//// sendCommand("TAKEOFF"+"___"+angle+"___"+String.valueOf(distance)); +//// } catch (UnknownHostException e) { +//// throw new RuntimeException(e); +//// } +// UdpReceiveThread udpReceiveThread = new UdpReceiveThread(); +// udpReceiveThread.start(); +// +// Log.i(TAG, "onClick: 2222222222222222222222222"); +// +// } +// }); +// dialog.show(); +// } +//////////////////////////////滑动开关////////////////////////////// + public static class SlideUnlockView extends View{ + + private final int BG_COLOR = Color.parseColor("#2D2E32"); // 背景颜色 + private static final int GUIDE_TEXT_COLOR = Color.WHITE; // 引导文本颜色 + private static final int GUIDE_TEXT_SIZE = 100; // 引导文本大小 + private static final int INDICATOR_COLOR = Color.WHITE; // 指示器颜色 + private static final int INDICATOR_RADIUS = 40; // 指示器半径 + private static final int INDICATOR_GAP = 300; // 指示器间距 + private static final int ARROW_COLOR = Color.WHITE; // 箭头颜色 + private static final int ARROW_SIZE = 20; // 箭头大小 + + private static final int STATE_LOCKED = 0; // 锁屏状态 + private static final int STATE_DRAGGING = 1; // 拖动状态 + private static final int STATE_UNLOCKED = 2; // 解锁状态 + + private Paint mPaint; + private Path mPath; + private int mViewWidth; + private int mViewHeight; + private int mIndicatorCount; + private int mCurrentIndex; + private float mLastX; + private boolean mIsUnlocked; + private int mState; + + private OnUnlockListener mOnUnlockListener; + + public abstract static class OnUnlockListener { + public class SimpleOnUnlockListener extends OnUnlockListener { + @Override + public void onUnlock() { + // 默认空实现 + } + } + public abstract void onUnlock(); + } + + public void setOnUnlockListener(OnUnlockListener listener) { + this.mOnUnlockListener = listener; + } + + public SlideUnlockView(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + private void init() { + mPaint = new Paint(); + mPaint.setAntiAlias(true); // 抗锯齿 + mPaint.setStyle(Paint.Style.FILL); + + mPath = new Path(); + + mIsUnlocked = false; + mState = STATE_LOCKED; + + // 指示器个数为 3 + mIndicatorCount = 3; + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + mViewWidth = w; + mViewHeight = h; + } + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + switch (mState) { + case STATE_LOCKED: + drawGuideText(canvas); + drawIndicatorCircles(canvas); + break; + case STATE_DRAGGING: + drawUnlockPath(canvas); + drawUnlockArrow(canvas); + break; + case STATE_UNLOCKED: + if (mOnUnlockListener != null) { + mOnUnlockListener.onUnlock(); + } + break; + } + } + + private void drawGuideText(Canvas canvas) { + mPaint.setColor(BG_COLOR); + canvas.drawRect(0, 0, mViewWidth, mViewHeight, mPaint); + + mPaint.setColor(GUIDE_TEXT_COLOR); + mPaint.setTextSize(GUIDE_TEXT_SIZE); + String guideText = "即将起飞"; + float textWidth = mPaint.measureText(guideText); + float textX = mViewWidth / 2 - textWidth / 2; + float textY = mViewHeight * 2 / 3; + canvas.drawText(guideText, textX, textY, mPaint); + } + + private void drawIndicatorCircles(Canvas canvas) { + mPaint.setColor(INDICATOR_COLOR); + float cy = mViewHeight / 2; + float startX = mViewWidth / 2 - INDICATOR_GAP * (mIndicatorCount - 1) / 2; + float radius = INDICATOR_RADIUS; + Path path = new Path(); + for (int i = 0; i < mIndicatorCount; i++) { + float cx = startX + INDICATOR_GAP * i; + path.addCircle(cx, cy, radius, Path.Direction.CCW); + } + canvas.drawPath(path, mPaint); + } + + private void drawUnlockPath(Canvas canvas) { + mPaint.setColor(INDICATOR_COLOR); + float cy = mViewHeight / 2; + float startX = mViewWidth / 2 - INDICATOR_GAP * (mIndicatorCount - 1) / 2; + float currentX = Math.max(Math.min(mLastX, mViewWidth - INDICATOR_RADIUS), startX + INDICATOR_GAP * mCurrentIndex); + Path path = new Path(); + path.moveTo(startX + INDICATOR_RADIUS, cy); + path.lineTo(currentX - INDICATOR_RADIUS, cy); + path.arcTo(new RectF(currentX - INDICATOR_RADIUS, cy - INDICATOR_RADIUS, + currentX + INDICATOR_RADIUS, cy + INDICATOR_RADIUS), -90, 180); + path.lineTo(startX + INDICATOR_GAP * (mIndicatorCount - 1), cy); + canvas.drawPath(path, mPaint); + } + + private void drawUnlockArrow(Canvas canvas) { + mPaint.setColor(ARROW_COLOR); + mPaint.setStyle(Paint.Style.STROKE); + mPaint.setStrokeWidth(5); + Path arrowPath = new Path(); + float x = Math.max(Math.min(mLastX, mViewWidth - INDICATOR_RADIUS - ARROW_SIZE), mViewWidth / 2 + INDICATOR_GAP * (mCurrentIndex - 1)); + float y = mViewHeight / 2; + arrowPath.moveTo(x - ARROW_SIZE, y - ARROW_SIZE); + arrowPath.lineTo(x, y); + arrowPath.lineTo(x - ARROW_SIZE, y + ARROW_SIZE); + canvas.drawPath(arrowPath, mPaint); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + float x = event.getX(); + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + if (mState == STATE_LOCKED) { + mState = STATE_DRAGGING; + mCurrentIndex = 0; + invalidate(); + return true; + } + break; + case MotionEvent.ACTION_MOVE: + if (mState == STATE_DRAGGING) { + mLastX = x; + int index = (int) ((x - mViewWidth / 2) / INDICATOR_GAP); + index = Math.max(Math.min(index, mIndicatorCount - 1), 0); + if (index != mCurrentIndex) { + mCurrentIndex = index; + invalidate(); + } + if (mCurrentIndex == mIndicatorCount - 1) { + mState = STATE_UNLOCKED; + mIsUnlocked = true; + } + return true; + } + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + if (mState == STATE_DRAGGING) { + mState = STATE_LOCKED; + mCurrentIndex = 0; + invalidate(); + return true; + } + break; + } + return super.onTouchEvent(event); + } + } +} \ No newline at end of file