Extension: UDP. Send text. WiFi. Source code

In this Community you can find examples with various UDP extensions.

KIO4_UDP.java (deprecated code, see updated code in post #12)

Summary
package com.KIO4_UDP;
// Juan Antonio Villalpando 
// http://kio4.com/appinventor/299K_extension_UDP.htm
//  Diciembre 2022.

import com.google.appinventor.components.annotations.DesignerComponent;
import com.google.appinventor.components.annotations.DesignerProperty;
import com.google.appinventor.components.annotations.PropertyCategory;
import com.google.appinventor.components.annotations.SimpleEvent;
import com.google.appinventor.components.annotations.SimpleFunction;
import com.google.appinventor.components.annotations.SimpleObject;
import com.google.appinventor.components.annotations.SimpleProperty;
import com.google.appinventor.components.annotations.UsesPermissions;
import com.google.appinventor.components.common.ComponentCategory;
import com.google.appinventor.components.common.PropertyTypeConstants;
import com.google.appinventor.components.runtime.util.MediaUtil;
import com.google.appinventor.components.runtime.*;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
// Obtener IP
import java.net.SocketException;
import java.util.Enumeration;
import java.net.NetworkInterface;
import java.net.Inet4Address;

@DesignerComponent(version = 1,
    description = "Send/Receive UDP. WiFi. GotText needs a Clock component." + 
    "Juan Antonio Villalpando - KIO4.COM ",
    category = ComponentCategory.EXTENSION,
    nonVisible = true,
    iconName = "") 
@SimpleObject(external = true)
@UsesPermissions(permissionNames = "android.permission.INTERNET, android.permission.ACCESS_WIFI_STATE")

public class KIO4_UDP extends AndroidNonvisibleComponent implements Component {
    public static final int VERSION = 1;
    private ComponentContainer container;
	public static final String DEFAULT_GOT_TEXT = "";
	private String got_text = "";
	
	InetAddress toAddr;
    int toPort2;
    String text2;
    int fromPort2;
	
	int portToReceive2;
	int sizePacket2;
	DatagramSocket dsocket;

    public KIO4_UDP(ComponentContainer container) {
        super(container.$form());
        this.container = container;
		GotText(DEFAULT_GOT_TEXT);
    }
	
// Obtener el valor.
@SimpleProperty(category = PropertyCategory.BEHAVIOR)
public String GotText() {
	return got_text;
}

// Establecer el valor
@DesignerProperty(editorType = PropertyTypeConstants.PROPERTY_TYPE_STRING, defaultValue = KIO4_UDP.DEFAULT_GOT_TEXT)
@SimpleProperty(description = "This propertie changes with ToReceive block. It needs a Clock component.")
public void GotText(String nuevogotText) {
	this.got_text = nuevogotText;
}

	
////////////////////// ENVIAR PAQUETE  ////////////////////////////////////////////////////////////
@SimpleFunction(description = "Send Packet.")
public void SendPacket(String toIP, int toPort, String text, int fromPort)  { 
toPort2 = toPort;
text2 = text;
fromPort2 = fromPort;
      try {
            toAddr = InetAddress.getByName(toIP);
            } catch (Exception ex) { }

    Thread thread = new Thread(new Runnable(){
     public void run() {
       try {
	DatagramSocket ds = new DatagramSocket(fromPort2);  
    DatagramPacket dp = new DatagramPacket(text2.getBytes(), text2.length(), toAddr, toPort2);  
    ds.send(dp);  
	ds.disconnect();
	ds.close();
	ds = null;
            } catch (IOException e) { }
        }
      });
      thread.start();
}


////////////////////// RECIBIR PAQUETE  ////////////////////////////////////////////////////////////
@SimpleFunction(description = "Text is received in GotText propertie. Use GotText with a Clock component.")	
public void ToReceive(int portToReceive, int sizePacket) {
portToReceive2 = portToReceive;
sizePacket2 = sizePacket;
Thread thread = new Thread(new Runnable(){
       public void run() {
       try {
        dsocket = new DatagramSocket(portToReceive2);
        byte[] buffer = new byte[sizePacket2];
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
        while (true) {
            dsocket.receive(packet);
            String aText = new String(buffer, 0, packet.getLength());
			got_text = aText;
       }
            } catch (IOException e) { }
        }
      });  
      thread.start();
}
////////////////////////////////////////////////////////////////////////////////////////
@SimpleFunction(description = "Close to receive.")	
public void CloseToReceive() {
	//dsocket.disconnect();
    dsocket.close();
}
////////////////////////////////////////////////////////////////////////////////////////
@SimpleFunction(description = "Get local IP.")
// http://www.java2s.com/example/java-api/java/net/networkinterface/getnetworkinterfaces-0-1.html
public String GetLocalIp() {
    try {
        for (Enumeration en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) 
		{
            NetworkInterface intf = en.nextElement();
            for (Enumeration enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
                InetAddress inetAddress = enumIpAddr.nextElement();
                if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
                    return inetAddress.getHostAddress();
                }
            }
        }
    } catch (SocketException ex) {ex.printStackTrace(); }
    return null;
}

}
  • It is a very simple extension, it can be modified and improved.
  • Let's see several examples...

You can download the extension and the example of...
http://kio4.com/appinventor/299K_extension_UDP.htm

- Designer.

- Blocks.

4 Likes

2.- Send and receive text the same device.

  • To do the first test we run the application (it works in MIT Companion).
    We write IP of the device, in my case 192.168.1.2

  • We establish in "To Port" the port to which it will send, in this case 3333.

  • In "From Port" the port from which it will send, in this case: 3334 (must be different from "To Port").

  • In "This device will...", we write the port where we will receive the information, in this case: 3333.

  • We write a Text to send and we will receive it in the same application.

  • In this example the application sends and receives the text.

extension_udp11

2 Likes

3.- Chat with two mobiles.

  • In each mobile we put the IP and the port of the other mobile ("To IP" and "To Port"), we also establish the port through which we will receive the information.

1 Like

4.- Broadcast.

  • If instead of establishing the IP of a device, we write To IP: 255.255.255.255 the text will be sent to the entire network, and it will "enter" those devices that have port 4444 (in this example) activated with UDP.

2 Likes

5.- Comments.

If we want to send text with accents, tildes,... we will use the Web component with the UriEncode and UriDecode blocks.

  • If in "To Port" we put 0, it will be sent to a random port every time we send a message.

  • If in "To IP" we put 255.255.255.255 it will be sent in Broadcast, that is to say to the entire local network.

1 Like

can we fire an event here? rather than fetch it by a timer?

That was my first intention, to create an event, but I got an error in code execution and took the easy way out: a property.

you need to fire a event on UI thread.

activity.runOnUI Thread (new runnable.....)

Yes, I knew it. In my code I started with "activity.runOnUI Thread (new runnable)" and it gave me an error, so I removed it and put the property.

Pixel 4XL (Android 12)

Can anyone test if Ulrich's extension works with Android >10, please?
p118B_ESP32_UDP.aia (53.7 KB)

https://community.appinventor.mit.edu/t/esp32-with-udp-send-receive-text-chat-mobile-mobile-udp-testing-extension-udp-by-ullis-ulrich-bien/72664/2

I was able to fix the ability to use event.

KIO4_UDP.java

Summary
package com.KIO4_UDP;
//  ?© Juan Antonio Villalpando 
// http://kio4.com/appinventor/299K_extension_UDP.htm
//  Diciembre 2022.

import com.google.appinventor.components.annotations.DesignerComponent;
import com.google.appinventor.components.annotations.DesignerProperty;
import com.google.appinventor.components.annotations.PropertyCategory;
import com.google.appinventor.components.annotations.SimpleEvent;
import com.google.appinventor.components.annotations.SimpleFunction;
import com.google.appinventor.components.annotations.SimpleObject;
import com.google.appinventor.components.annotations.SimpleProperty;
import com.google.appinventor.components.annotations.UsesPermissions;
import com.google.appinventor.components.common.ComponentCategory;
import com.google.appinventor.components.common.PropertyTypeConstants;
import com.google.appinventor.components.runtime.util.MediaUtil;
import com.google.appinventor.components.runtime.*;

import android.app.Activity;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
// Obtener IP
import java.net.SocketException;
import java.util.Enumeration;
import java.net.NetworkInterface;
import java.net.Inet4Address;

@DesignerComponent(version = 1,
    description = "Send/Receive UDP. WiFi. GotText needs a Clock component." + 
    "Juan Antonio Villalpando - KIO4.COM ",
    category = ComponentCategory.EXTENSION,
    nonVisible = true,
    iconName = "") 
@SimpleObject(external = true)
@UsesPermissions(permissionNames = "android.permission.INTERNET, android.permission.ACCESS_WIFI_STATE")

public class KIO4_UDP extends AndroidNonvisibleComponent implements Component {
    public static final int VERSION = 1;
    private ComponentContainer container;
	public static final String DEFAULT_GOT_TEXT = "";
	private String got_text = "-";
    private final Activity activity;
	
	InetAddress toAddr;
    int toPort2;
    String text2;
    int fromPort2;
	
	int portToReceive2;
	int sizePacket2;
	DatagramSocket dsocket;

    public KIO4_UDP(ComponentContainer container) {
        super(container.$form());
        this.container = container;
		GotText(DEFAULT_GOT_TEXT);
        activity = (Activity) container.$context();
    }
	
// Obtener el valor.
@SimpleProperty(category = PropertyCategory.BEHAVIOR)
public String GotText() {
	return got_text;
}

// Establecer el valor
@DesignerProperty(editorType = PropertyTypeConstants.PROPERTY_TYPE_STRING, defaultValue = KIO4_UDP.DEFAULT_GOT_TEXT)
@SimpleProperty(description = "This propertie changes with ToReceive block. It needs a Clock component.")
public void GotText(String nuevogotText) {
	this.got_text = nuevogotText;
}

	
////////////////////// ENVIAR PAQUETE  ////////////////////////////////////////////////////////////
@SimpleFunction(description = "Send Packet.")
public void SendPacket(String toIP, int toPort, String text, int fromPort)  { 
toPort2 = toPort;
text2 = text;
fromPort2 = fromPort;
      try {
            toAddr = InetAddress.getByName(toIP);
            } catch (Exception ex) { }

    Thread thread = new Thread(new Runnable(){
     public void run() {
       try {
	DatagramSocket ds = new DatagramSocket(fromPort2);  
    DatagramPacket dp = new DatagramPacket(text2.getBytes(), text2.length(), toAddr, toPort2);  
    ds.send(dp);  
	ds.disconnect();
	ds.close();
	ds = null;
            } catch (IOException e) { }
        }
      });
      thread.start();
}


////////////////////// RECIBIR PAQUETE  ////////////////////////////////////////////////////////////
@SimpleFunction(description = "Text is received in GotText propertie. Use GotText with a Clock component.")	
public void ToReceive(int portToReceive, int sizePacket) {
portToReceive2 = portToReceive;
sizePacket2 = sizePacket;

Thread thread = new Thread(new Runnable(){
       public void run() {
       try {
        dsocket = new DatagramSocket(portToReceive2);
        byte[] buffer = new byte[sizePacket2];
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
        while (true) {
            dsocket.receive(packet);
            String aText = new String(buffer, 0, packet.getLength());
			got_text = aText;	
					    activity.runOnUiThread(new Runnable(){
						public void run() {
						TextReceived(got_text);
						}
						  });  
       }
            } catch (IOException e) { }
        }	
      });  
      thread.start();
}

////////////////////////////////////////////////////////////////////////////////////////
@SimpleFunction(description = "Close to receive.")	
public void CloseToReceive() {
	//dsocket.disconnect();
    dsocket.close();
}
////////////////////////////////////////////////////////////////////////////////////////
@SimpleFunction(description = "Get local IP.")
// http://www.java2s.com/example/java-api/java/net/networkinterface/getnetworkinterfaces-0-1.html
public String GetLocalIp() {
    try {
        for (Enumeration en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) 
		{
            NetworkInterface intf = en.nextElement();
            for (Enumeration enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
                InetAddress inetAddress = enumIpAddr.nextElement();
                if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
                    return inetAddress.getHostAddress();
                }
            }
        }
    } catch (SocketException ex) {ex.printStackTrace(); }
    return null;
}

// Bloques de EVENTOS.
    @SimpleEvent(description = "Got text from ToReceive block.")
    public void TextReceived(String text){
        EventDispatcher.dispatchEvent(this, "TextReceived", text);
    }  
	
}

http://kio4.com/appinventor/299K_extension_UDP.htm

  • I've only tested it on Android 5 and Android 9.
1 Like