12 "Wanli" Raspberry Pi car - socket learning (Android sending and receiving)
[Copy link]
Previously, we introduced the code for sending using the UDP protocol on Android, but implementing the receiving function is relatively complicated. Here, we can directly use the library written by predecessors to achieve twice the result with half the effort.
Find a UDP encapsulation on GitHub, see the source code at the end of the article for details.
APP building steps
Create a new blank project and add network usage permissions in AndroidManifest.xml, just like in the previous article.
Copy the UdpClient.java file to the same folder as MainActivity.java. Do not copy it directly into the folder. If you copy it on Android Studio, the package name will be automatically changed.
Modify the layout file "activity_main.xml". The layout is relatively complex. You can see the final effect picture.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="20dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="连接状态:"/>
<TextView
android:id="@+id/tv_state"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:text="未连接"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="服务器IP地址:"/>
<EditText
android:id="@+id/et_ip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:text="192.168.31.34"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="服务器端口号:"/>
<EditText
android:id="@+id/et_port"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:text="1234"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn_connect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="连接"
android:onClick="onClick"
android:layout_weight="1"/>
<Button
android:id="@+id/btn_disconnect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="断开"
android:onClick="onClick"
android:layout_weight="1"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发送内容:"/>
<EditText
android:id="@+id/et_send"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:text="lb8820265"/>
</LinearLayout>
<Button
android:id="@+id/btn_send"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="发送"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="接收内容:"/>
<Button
android:id="@+id/btn_clear"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="清空接收"/>
</LinearLayout>
<ScrollView
android:id="@+id/sv_receive"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/et_receive"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="@color/black"
android:background="@null"/>
</ScrollView>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Write the MainActivity.java function, which mainly initializes the listener and writes the corresponding functions of each control.
package com.example.lb_socket_android;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.util.Xml;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Arrays;
public class MainActivity extends AppCompatActivity {
private EditText et_ip;
private EditText et_port;
private EditText et_send;
private EditText et_receive;
private TextView tv_state;
private ScrollView sv_receive;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_ip= (EditText) findViewById (R.id.et_ip);
et_port= (EditText) findViewById (R.id.et_port);
et_send=(EditText) findViewById (R.id.et_send);
tv_state= (TextView) findViewById (R.id.tv_state);
et_receive= (EditText) findViewById (R.id.et_receive);
sv_receive= (ScrollView) findViewById (R.id.sv_receive);
UdpClient.getInstance().setOnDataReceiveListener(dataReceiveListener);
}
public void onClick(View view){
switch (view.getId()) {
case R.id.btn_clear:
et_receive.setText("");
break;
case R.id.btn_send:
if (UdpClient.getInstance().isConnect()) {
byte[] data=et_send.getText().toString().getBytes();
String str = new String(data);
Log.i("TAG_log",str);
UdpClient.getInstance().sendByteCmd(data,1001);
} else {
Toast.makeText(MainActivity.this,"尚未连接,请连接Socket",Toast.LENGTH_SHORT).show();
}
break;
case R.id.btn_connect:
String ip = et_ip.getText().toString();
String port = et_port.getText().toString();
if(TextUtils.isEmpty(ip)){
Toast.makeText(MainActivity.this,"IP地址为空",Toast.LENGTH_SHORT).show();
return;
}
if(TextUtils.isEmpty(port)){
Toast.makeText(MainActivity.this,"端口号为空",Toast.LENGTH_SHORT).show();
return;
}
UdpClient.getInstance().connect(ip, Integer.parseInt(port));
break;
case R.id.btn_disconnect:
UdpClient.getInstance().disconnect();
tv_state.setText("未连接");
break;
default:
break;
}
}
private UdpClient.OnDataReceiveListener dataReceiveListener = new UdpClient.OnDataReceiveListener() {
@Override
public void onConnectSuccess() {
Log.i("TAG_log","onDataReceive connect success");
tv_state.setText("已连接");
}
@Override
public void onConnectFail() {
Log.e("TAG_log","onDataReceive connect fail");
tv_state.setText("未连接");
}
@Override
public void onDataReceive(byte[] buffer, int size, int requestCode) {
//获取有效长度的数据
byte[] data = new byte[size];
System.arraycopy(buffer, 0, data, 0, size);
String oxValue = new String(data);
Log.i("TAG_log","onDataReceive requestCode = "+requestCode + ", content = "+oxValue);
et_receive.append(oxValue + "\n");
sv_receive.fullScroll(View.FOCUS_DOWN);
}
};
@Override
protected void onDestroy() {
UdpClient.getInstance().disconnect();
super.onDestroy();
}
}
How to run
- Connect the mobile phone and PC to the same router, obtain the IP address of the PC, and modify the IP address in the APP code.
- Compile and run the socket_UDP_win_server.cpp written previously on Windows.
- Compile and run the app on a real device, first click the "Connect" button, then click the "Send" button.
Operation effect
question
Now that the communication problem has been solved, the next step is programming the car, such as how to control the motor, how to control the speed, etc.
Source code
GitHub:
Gitee:
|