Control a relay using an Android by Wi-Fi - android

How can I turn on or turn off a switch using Android and a Wi-Fi connection?
I have used SparkFuns IOIO to control relays. But how do I do it wirelessly?

I have a project just like this. Mine is sending position data for a steering system, but the idea is the same. I'll finish uploading it to Google Code soon. You can check it out at PowerWheelino.
The basic structure is this:
Touch event on Android sends data (over UDP) to the server.
The UDP server (WRT54G router in this case) receives the data and forwards it over serial to the Arduino.
The Arduino decides what to do with the data from the serial connection.
Keep in mind that the Arduino automatically resets when receiving data over serial (outside of the IDE Serial interface). See my post here on this topic and ways to get around it. Knowing this previously would have saved me a lot of troubleshooting.
Disclaimer:
This code requires some minor modification to accomplish what was requested by the OP. Since you've already made a working Android program with IOIO and an Arduino sketch, I assume this is within your abilities.
Here's the Android UDP client code:
Execute UdpClient::sendData() on touch event or button press.
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import android.util.Log;
public class UdpClient {
String messageStr;
DatagramSocket s;;
int server_port;
InetAddress local;
int msg_length;
byte[] message;
public UdpClient (String ipAddress, int port){
server_port = port;
try {
local = InetAddress.getByName(ipAddress);
s = new DatagramSocket();
}
catch (Exception e) {
e.printStackTrace();
Log.d("Powerwheelino",e.getStackTrace() + "error");
}
}
public boolean sendData(byte drive, byte steering){
byte drvByte = (byte) (drive & 0xFF);
byte steerByte = (byte) (steering & 0xFF);
message = new byte[2];
message[0] = drvByte;
message[1] = steerByte;
msg_length = message.length;
//message = messageStr.getBytes();
try {
DatagramPacket p = new DatagramPacket(message, msg_length,local,server_port);
s.send(p);
}
catch (Exception e) {
// TODO Auto-generated catch block
Log.d("Powerwheelino", e.getStackTrace() +"ERROR ");
e.printStackTrace();
return false;
}
return true;
}
}
Here's the listening UDP server (C++) code
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <SerialStream.h>
using namespace std;
class udp_server {
int sock;
int bytes_read;
socklen_t addr_len;
struct sockaddr_in server_addr , client_addr;
public:
udp_server(int portNum)
{
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("Socket");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(portNum);
server_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(server_addr.sin_zero),8);
if (bind(sock,(struct sockaddr *)&server_addr,
sizeof(struct sockaddr)) == -1)
{
perror("Bind");
exit(1);
}
addr_len = sizeof(struct sockaddr);
printf("\nUDPServer Waiting for client on port %d", portNum);
fflush(stdout);
}
int listen(char recv_data[]) {
while (1)
{
bytes_read = recvfrom(
sock,
recv_data,
1024,
0,
(struct sockaddr *)&client_addr,
&addr_len
);
recv_data[bytes_read] = '\0';
printf("\n(%s , %d) said : ",inet_ntoa(client_addr.sin_addr),
ntohs(client_addr.sin_port));
printf("%s", recv_data);
string drive;
string direction;
int speed, angle;
if ((recv_data[0] & 128) > 0) {
drive = "Fwd";
}
else {
drive = "Rev";
}
if ((recv_data[1] & 128) > 0) {
direction = "Left";
}
else {
direction = "Right";
}
speed = recv_data[0] & 127;
angle = recv_data[1] & 127;
printf("\t %s # %d and %s # %d",
drive.c_str(),
speed,
direction.c_str(),
angle);
fflush(stdout);
}
return 0;
}
};
Here's a snippet of the serial communication to the Arduino using LibSerial:
LibSerial::SerialStream myss;
SerialComm(int argc, char** argv) {
myss = new LibSerial::SerialStream("/dev/ttyS0", ios_base::out);
myss.SetBaudRate(LibSerial::SerialStreamBuf::BAUD_57600);
myss.SetCharSize(LibSerial::SerialStreamBuf::CHAR_SIZE_8);
myss.SetFlowControl(LibSerial::SerialStreamBuf::FLOW_CONTROL_NONE);
myss.SetParity(LibSerial::SerialStreamBuf::PARITY_NONE);
myss.SetNumOfStopBits(1);
const int Dsize = 2;
char buffer[1];
buffer[0] = 125; //0b00000001;
buffer[1] = '\0';
bitset(buffer[0]);
//myss << buffer;
myss.write(buffer,1);
//myss.Close();
}

You could use an Arduino with an Ethernet Shield - or possibly a Netduino. Basically, any device with wireless internet capabilities, since that is the only wireless protocol Android uses - besides Bluetooth (or NFC). When the user presses a button, you could open a Socket or a BluetoothSocket to communicate to the second device that it needs to open the switch. Fairly simple - if you have a wireless home network, then your device could be plugged in to your router with a physical wire - as long as your Android device and your microprocessor are on the same network. There might be other wireless options you could use - these are just the simplest I could thing of. Hope this helps!

That's why how I did it with my iPhone (should be the same on Android):
run a TCP server on a computer connected to the same network as your phone and by USB/serial to the Arduino.
This server should forward all incoming data coming through Wi-Fi from your Android phone through USB to the Arduino.
The phone should run a TCP client which sends a simple one-byte (maybe zero and non-zero) command
The Arduino shall be programmed so it listens for incoming serial data via interrupts; if a byte arrives it decides if it should switch the I/O pin on or off.

You can also use a Rugged Circuits Yellowjacket. It has a Wifi on board and can serve simple web pages and control inputs/outputs.

Related

Arduino Mega ADK strange acc.write() behavior (huge delay) NAK issue seemd to be confirmed. Android generates NAK's as a result of acc.write

I'm trying to communicate between Arduino Mega Adk (ADK 2011) and android device.
Something goes ok, but something goes completely wrong.
Transfer data from Android to Arduino via acc.read from Arduino side works fine.
But when i try to send some bytes from Arduino to Android - something strange happens.
First of all here is Arduino sketch:
#include <Max3421e_constants.h>
#include <Max3421e.h>
#include <Usb.h>
#include <AndroidAccessory.h>
#define COMMAND_LED 0x2
#define TARGET_PIN_18 0x12
#define TARGET_PIN_19 0x13
#define V_ON 0x1
#define V_OFF 0x0
#define PIN_18 18
#define PIN_19 19
#define INPUT_PIN 30
AndroidAccessory acc("Google, Inc.",
"DemoKit",
"Ololo device board",
"1.0",
"http://www.android.com",
"0000000012345678");
byte rcvmsg[3];
byte sndmsg[3];
int buttonState = 0;
void setup();
void loop();
void led_setup(){
pinMode(PIN_18, OUTPUT);
pinMode(PIN_19, OUTPUT);
pinMode(INPUT_PIN, INPUT);
}
void setup()
{
Serial.begin(115200);
Serial.print("\r\nStart");
led_setup();
acc.powerOn();
}
void loop()
{
if (acc.isConnected()) {
buttonState = digitalRead(INPUT_PIN);
if (buttonState == 1){
sndmsg[0] = 0x2;
sndmsg[1] = 0x1;
sndmsg[2] = 0x1;
int len = acc.write(sndmsg, 3);
digitalWrite(PIN_19, HIGH);
}
else {
//Nothing here for test
}
}
//usefull test for button
buttonState = digitalRead(INPUT_PIN);
if (buttonState == 1){
digitalWrite(PIN_19, HIGH);
}
else {
digitalWrite(PIN_19, LOW);
}
}
Ok. When acc.write() is executed it takes up to ~1 second to transfer data to android. And this time doesn't depend on number of bytes in sndmsg. Only if i execute acc.write(sndmsg,0) (sending 0 bytes) - everything goes fast.
That is a little bit disturbing. I've tried to change board to another one but have got the same result.
Any advices? may be that is a common bug, but there is no such much information in web.
UPD:
Wrote some very simple code, that only sends 3 bytes via acc.write.
here it is:
#include <Max3421e_constants.h>
#include <Max3421e.h>
#include <Usb.h>
#include <AndroidAccessory.h>
AndroidAccessory acc("Google, Inc.",
"DemoKit",
"Demokit board",
"1.0",
"http://www.android.com",
"0000000012345678");
byte msg[3];
unsigned long time;
void setup();
void loop();
void led_setup(){
}
void setup()
{
Serial.begin(115200);
Serial.print("\r\nStart");
acc.powerOn();
}
void loop()
{
if (acc.isConnected()) {
Serial.print("\r\nis Connected");
msg[0] = 0x1;
msg[1] = 0x1;
msg[2] = 0x1;
//Serial.print("\r\nSending");
time = millis();
Serial.print ("\r\nBefore write\r\n");
Serial.print (time);
acc.write(msg, 3);
time = millis();
Serial.print("\r\nAfter write: \r\n");
Serial.print (time);
//delay(500);
}
}
And it's debug output is:
is Connected
Before write
6983
After write:
10958
is Connected
Before write
10958
After write:
14491
is Connected
and so on. So on some reasons acc.write takes a lot of time and there is no data in the android app.
New UPD (19.01.2015):
Today i've performed some experiments. Here are results.
First, i've looked into AndroidAccessory.cpp and found write function:
int AndroidAccessory::write(void *buff, int len)
{
usb.outTransfer(1, out, len, (char *)buff);
return len;
}
Ok, then i looked into usb host shield library and found there usb.cpp with outTransfer fucntion, that returns error code if ouccured and 0x00 if everything is ok.
So i modified write function to return an error code instead of lenght, like this:
int AndroidAccessory::write(void *buff, int len)
{
byte rcode;
rcode = usb.outTransfer(1, out, len, (char *)buff);
return int(rcode);
}
and recived "4" as result.
According to MAX3421Econstants.h it is hrNAK (0x04) error code.
Any ideas? Looks like accessory does not recive NAKs from Android and write fails as a result.
Situation update:
Did some research. There is a hell of NAK's when accessory is connected. Here is dump from usb connector:
i found the solution. And it is very simple - i didn't setup communication with accessory correctly.
This is not an Arduino problem. Arduino works fine.
It is just how android interacts with android accessory.
So, results:
When AndroidAccessory is plugged to Android and Android haven't setup
communication with the accessory yet, Android OS will send a lot of
USB NAKs to the accessory and this is normal.
You must be careful
during setuping communication with the accessory. If you make some
mistakes, you can receive same situation: Probably possible to write
to the accessory, but accessory isn't possible to write to the
android.
If UsbManager opens accessory correctly, it stops sending
NAKs and starts recieve data from arduino.
It is a little bit strange for me, because it was really hard to found a problem: i have an application, written according to this manual: http://developer.android.com/guide/topics/connectivity/usb/accessory.html But, because i'm not very familiar with android, it seems that i've done some mistakes and receive strange behavior:
i was able to write to arduino
i was able to retrive information about arduino as android accessory
it was possible to ask for permissions
but when arduino tries to write to android, it recievs a lot of NAKs
So i decided to rewrite program in more simple way, just with one function and tried to do it in right way. And after some debugging it finally started to work as i want.
So thank everyone, who spend time for reading this.
Bonus: dump of normal packet, ended with EOP not NAK
UPD 26.01.2015:
I found problem and it was in my android code.
here is explanation:
Android developer's manual said that function, which set up communication with accessory must start it's own thread in which all communications with input and output streams are held. Smth like this:
private void openAccessory() {
Log.d(TAG, "openAccessory: " + accessory);
mFileDescriptor = mUsbManager.openAccessory(mAccessory);
if (mFileDescriptor != null) {
FileDescriptor fd = mFileDescriptor.getFileDescriptor();
mInputStream = new FileInputStream(fd);
mOutputStream = new FileOutputStream(fd);
Thread thread = new Thread(null, this, "AccessoryThread");
thread.start();
}
}
I really messed this thing up. Forgot about creating new thread in openAccessory function and tried to do it in different place. And recieve a hell of NAK's. Then i've changed my code and add some debug-like run() function like this:
public void run() {
final byte[] buffer = new byte[16384];
int ret = 0;
int i = 0;
while (i<50) {
try {
ret = mInputStream.read(buffer);
i++;
Thread.sleep(500);
} catch (IOException e) {
break;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
And until this run method exists (while i < 50) android reads arduino correctly. And when thread ends up (i > 50) - Arduino starts to readout Error Code 4 (NAK) from Android.
That's all folks.

Cannot connect to Bluetooth/BlueZ server: Could not create RFCOMM socket

I am trying to create a simple and custom Bluetooth connection between my Linux laptop and Android phone. On the Linux side of things, I use the BlueZ libbluetooth library to set up a server. The code for it is very similar to others I've seen floating around on github:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
#include <bluetooth/rfcomm.h>
sdp_session_t *register_service();
int main(int argc, char **argv)
{
struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
char buf[1024] = { 0 };
char str[1024] = { 0 };
int s, client, bytes_read;
sdp_session_t *session;
socklen_t opt = sizeof(rem_addr);
session = register_service();
s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
loc_addr.rc_family = AF_BLUETOOTH;
loc_addr.rc_bdaddr = *BDADDR_ANY;
loc_addr.rc_channel = (uint8_t) 11;
printf("Trying to bind...");
fflush(stdout);
bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));
printf("bound\n");
fflush(stdout);
printf("Waiting for connection...");
fflush(stdout);
listen(s, 1);
client = accept(s, (struct sockaddr *)&rem_addr, &opt);
ba2str( &rem_addr.rc_bdaddr, buf );
fprintf(stderr, "accepted connection from %s\n", buf);
memset(buf, 0, sizeof(buf));
bytes_read = read(client, buf, sizeof(buf));
if( bytes_read > 0 ) {
printf("received [%s]\n", buf);
}
sprintf(str,"to Android.");
printf("sent [%s]\n",str);
write(client, str, sizeof(str));
close(client);
close(s);
sdp_close( session );
return 0;
}
sdp_session_t *register_service()
{
uint32_t svc_uuid_int[] = { 0x00000000,0x00000000,0x00000000,0x3233 };
uint8_t rfcomm_channel = 11;
const char *service_name = "Remote Host";
const char *service_dsc = "What the remote should be connecting to.";
const char *service_prov = "Your mother";
uuid_t root_uuid, l2cap_uuid, rfcomm_uuid, svc_uuid;
sdp_list_t *l2cap_list = 0,
*rfcomm_list = 0,
*root_list = 0,
*proto_list = 0,
*access_proto_list = 0;
sdp_data_t *channel = 0, *psm = 0;
sdp_record_t *record = sdp_record_alloc();
// set the general service ID
sdp_uuid128_create( &svc_uuid, &svc_uuid_int );
sdp_set_service_id( record, svc_uuid );
sdp_list_t service_class = {NULL, &svc_uuid};
sdp_set_service_classes( record, &service_class);
// make the service record publicly browsable
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
root_list = sdp_list_append(0, &root_uuid);
sdp_set_browse_groups( record, root_list );
// set l2cap information
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
l2cap_list = sdp_list_append( 0, &l2cap_uuid );
proto_list = sdp_list_append( 0, l2cap_list );
// set rfcomm information
sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
channel = sdp_data_alloc(SDP_UINT8, &rfcomm_channel);
rfcomm_list = sdp_list_append( 0, &rfcomm_uuid );
sdp_list_append( rfcomm_list, channel );
sdp_list_append( proto_list, rfcomm_list );
// attach protocol information to service record
access_proto_list = sdp_list_append( 0, proto_list );
sdp_set_access_protos( record, access_proto_list );
// set the name, provider, and description
sdp_set_info_attr(record, service_name, service_prov, service_dsc);
int err = 0;
sdp_session_t *session = 0;
// connect to the local SDP server, register the service record, and
// disconnect
session = sdp_connect( BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY );
err = sdp_record_register(session, record, 0);
// cleanup
//sdp_data_free( channel );
sdp_list_free( l2cap_list, 0 );
sdp_list_free( rfcomm_list, 0 );
sdp_list_free( root_list, 0 );
sdp_list_free( access_proto_list, 0 );
return session;
}
I am able to run the server side code in Linux without error:
$ ./bluetooth-server
Trying to bind...bound
Waiting for connection...
I am then able to use sdptool to see my RFCOMM socket and service (description, channel number, and all other information look correct):
Service Name: Remote Host
Service Description: What the remote should be connecting to.
Service Provider: Your mother
Service RecHandle: 0x10009
Service Class ID List:
UUID 128: 00000000-0000-0000-0000-000033320000
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 11
Now, on the Android side of things I first pair the phone to the Linux server via the standard settings screen. Once paired, I then use code on the Android side of things to scan for Bluetooth devices, and if it is my Linux device then I try to connect to it. I have tried two different methods that people have suggested on stack overflow to make the connection:
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if(device.getName().equals("ubuntu-0")) {
try {
mBluetoothAdapter.cancelDiscovery();
// This returns the value 00001103-0000-1000-8000-00805f9b34fb
UUID uuid = device.getUuids()[0].getUuid();
// This does not work
//BluetoothSocket tmp = device.createRfcommSocketToServiceRecord(uuid);
// And neither does this
Method m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
BluetoothSocket tmp = (BluetoothSocket) m.invoke(device, 11); // Match channel 11
tmp.connect(); // Exception is thrown here
}
catch(Exception e) {
Log.e("BT", "Could not create RFCOMM socket " + e.toString());
}
}
}
I keep getting the following Exception being thrown when I actually try the tmp.connect() call:
03-20 14:20:13.089: E/BT(16915): Could not create RFCOMM socket
java.io.IOException: read failed, socket might closed or timeout, read ret: -1
Does anyone see what I am doing wrong here in trying to create the connection? Note that I do get a UUID returned when I call UUID uuid = device.getUuids()[0].getUuid(); ... this leads me to believe that the pairing is OK, which returns the value 00001103-0000-1000-8000-00805f9b34fb.
Maybe this could be reason if you pair your device before running ./bluetooth-server then rfcomm service record is not added and remote device will not information about this and if remote device does not do the service discovery then it will not be able to connect to your device.

How to use netlink sockets for kernel - userspace communication Android

I'm trying to write kernel module for android to communicate with userspace Service so my app can display some information about the kernel. So far I've tried several examples I found on the web and none of them works. The idea is for kernel to send updates and service would then pick them up. ioctl is not a solution because the communication needs to be event driven, and initiated from kernel. C code for both jni and kernel module would be great if anyone knows how to do this.
Here's a code snippet that I've used (excluding error checking of return values for conciseness) where the netlink socket communication is driven by the kernel (i.e. the kernel is the sender, user program is the receiver).
Kernel module
#include <net/sock.h>
#include <net/netlink.h>
#include <linux/skbuff.h>
#include <string.h>
#define MY_GROUP 1
struct sock* socket;
struct sk_buff* socket_buff;
static void nl_receive_callback (struct sk_buff *skb)
{
nlmsg_free(skb);
}
static void kernel_send_nl_msg(void)
{
struct nlmsghdr *nlsk_mh;
char* msg = "hello kernel";
socket = netlink_kernel_create(&init_net, NETLINK_USERSOCK, 1, nl_receive_callback, NULL, THIS_MODULE);
socket_buff = nlmsg_new(256, GFP_KERNEL);
nlsk_mh = nlmsg_put(socket_buff, 0, 0, NLMSG_DONE, strlen(msg), 0);
NETLINK_CB(socket_buff).pid = 0; // kernel pid
NETLINK_CB(socket_buff).dst_group = MY_GROUP;
strcpy(nlmsg_data(nlsk_mh), msg);
nlmsg_multicast(socket, socket_buff, 0, MY_GROUP, GFP_KERNEL);
return;
}
You'd fire this up as a result of your kernel event, e.g. in response to an ioctl or within your interrupt handling.
User Program
#include <sys/socket.h>
#include <linux/netlink.h>
#define MY_GROUP 1
void user_recieve_nl_msg(void)
{
int sock_fd;
struct sockaddr_nl user_sockaddr;
struct nlmsghdr *nl_msghdr;
struct msghdr msghdr;
struct iovec iov;
char* kernel_msg;
sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USERSOCK);
memset(&user_sockaddr, 0, sizeof(user_sockaddr));
user_sockaddr.nl_family = AF_NETLINK;
user_sockaddr.nl_pid = getpid();
user_sockaddr.nl_groups = MY_GROUP;
bind(sock_fd, (struct sockaddr*)&user_sockaddr, sizeof(user_sockaddr));
while (1) {
nl_msghdr = (struct nlmsghdr*) malloc(NLMSG_SPACE(256));
memset(nl_msghdr, 0, NLMSG_SPACE(256));
iov.iov_base = (void*) nl_msghdr;
iov.iov_len = NLMSG_SPACE(256);
msghdr.msg_name = (void*) &user_sockaddr;
msghdr.msg_namelen = sizeof(user_sockaddr);
msghdr.msg_iov = &iov;
msghdr.msg_iovlen = 1;
recvmsg(sock_fd, &msghdr, 0);
kernel_msg = (char*)NLMSG_DATA(nl_msghdr);
print("Kernel message: %s\n", kernel_msg); // print to android logs
}
close(sock_fd);
}
I use nlmsg_multicast() in the kernel rather than nlmsg_unicast() because to do a unicast, the kernel module would need to know the process id of your user process (so you'd need to add some extra implementation there).
Hope that helps!
I have successfully used netlink socket to communicate between kernel and user-space in Android. To use socket in non-blocking mode use the fcntl and select call.

android ad-hoc udp broadcast hangs on send(ndk)

I'm trying to send a broadcast message in my ad-hoc network - 192.168.2.x, using native c code.
But the app hangs on sendto(). btw the hang is not connected to the while, that wraps it, as I can see in debug, it only tries sendto() ones and hangs.
Is there something wrong with my code?
int broadcast(char* msg){
int bcast_sock;
struct sockaddr_in their_addr; // connector's address information
if((bcast_sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
LOGE("ERROR BROADCASTING , socket wasn't created");
}
int broadcastEnable=1;
int ret=setsockopt(bcast_sock, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable));
if(ret < 0)
{
LOGE("ERROR BROADCASTING, Coulnt set broadcast enable through socket options");
}
their_addr.sin_family = AF_INET; // host byte order
their_addr.sin_port = htons(BROADCAST_PORT); // short, network byte order
their_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
memset(&(their_addr.sin_zero), '\0', 8); // zero the rest of the struct
while(-1 == (int)sendto(bcast_sock, msg, strlen(msg), 0,
(struct sockaddr *)&their_addr, sizeof(struct sockaddr)));
return 0;
}
A couple of notes:
This of course are rooted phones.
If I broadcast using java broadcast, it works fine, I'm able to receive the broadcast ie:
datagramSocket.setBroadcast(true);
int receiverPort = 4949;
sendPacket = new DatagramPacket(data, data.length, IPAddress, receiverPort);
Non broadcast messages are also being sent and received using native code.
The CPU usage becomes ~ 95% .
I've also tried simply sending to 192.168.2.255.
any ideas?
I solved it by changing address conversion from:
their_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
to
inet_aton(IP,&their_addr.sin_addr);
where IP = "192.168.2.1"
Thanks for the help epx

Android UDP client not able to receive data on non-rooted phone

I have implemented a UDP client on android's native part(i.e. in C). Inorder to receive data from the server(PC) both my device and PC are connected over a wifi connection.
When the client is put on a rooted device, it is able to receive data from the server perfectly. However on a non-rooted device, although it doesnt show any error, it is not able to send/receive data form/to the server.
Below is my server code:
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<sys/stat.h>
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<fcntl.h>
int main()
{
int cont,create_socket,new_socket,addrlen,fd;
int bufsize = 3000;
int nameLen=0;
int client_address_size=0;
char *buffer = malloc(bufsize);
char fname[256];
struct sockaddr_in address,client;
if ((create_socket = socket(AF_INET,SOCK_DGRAM,0)) > 0)
printf("The socket was created\n");
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(15000);
if (bind(create_socket,(struct sockaddr *)&address,sizeof(address))== 0)
printf("Binding Socket\n");
nameLen=sizeof(address);
if (getsockname(create_socket,(struct sockaddr *)&address,&nameLen)<0)
{
printf("\n\ngetsockname() error\n");
exit(3);
}
printf("Port assigned is %d\n", ntohs(address.sin_port));
client_address_size=sizeof(client);
if(recvfrom(create_socket,fname, 255,0,(struct sockaddr *) &client,&client_address_size)<0)
{
printf("\n\nrecvfrom() failed\n");
exit(4);
}
printf("A request for filename %s Received..\n", fname);
if ((fd=open(fname, O_RDONLY))<0)
{
perror("File Open Failed");
exit(0);
}
while((cont=read(fd, buffer, bufsize))>0)
{
sleep(1);
sendto(create_socket,buffer,cont,0,(struct sockaddr *) &client,client_address_size);
printf("\n\nPacket sent\n");
}
sendto(create_socket,"*",1,0,(struct sockaddr *) &client,client_address_size);
printf("Request Completed\n");
return close(create_socket);
}
client code on android NDK:
JNIEXPORT void JNICALL Java_com_examplemyPlayer_startClient
(JNIEnv *env, jclass jobj, jint portNo, jstring argv1)
{
__android_log_print(ANDROID_LOG_DEBUG,"MYAPP","start client has entered....",NULL);
//int portno=portNo;
const char *servIP = (*env)->GetStringUTFChars(env, argv1, 0);
__android_log_print(ANDROID_LOG_DEBUG,"MYAPP","Server IP address:%s",servIP);
__android_log_print(ANDROID_LOG_DEBUG,"MYAPP","Server Port No.:%d",portno);
qBuff=(unsigned char *)malloc(sizeof(char)*Q_SIZE);//qBuff is a global pointer
int create_socket,cont;
int bytesWritten=0;
int bufsize = 3000;
int server_address_size=0;
char *buffer = malloc(bufsize);
char reqFname[8]="Bub.bin";
struct sockaddr_in address,server;
int serv_addr_size = sizeof(address);
if ((create_socket = socket(AF_INET,SOCK_DGRAM,0)) < 0)
__android_log_print(ANDROID_LOG_DEBUG,"MYAPP","The Socket was NOT created",NULL);
__android_log_print(ANDROID_LOG_DEBUG,"MYAPP","The Socket was successfully created",NULL);
address.sin_family = AF_INET;
address.sin_port = htons(15000);
address.sin_addr.s_addr=inet_addr(servIP);
if((sendto(create_socket, reqFname, sizeof(reqFname), 0,(struct sockaddr *) &address,sizeof(address)))==-1)
__android_log_print(ANDROID_LOG_DEBUG,"MYAPP","Error sending filename to server",NULL);
__android_log_print(ANDROID_LOG_DEBUG,"MYAPP","Request Accepted... \n\nReceiving File...",NULL);
server_address_size=sizeof(server);
__android_log_print(ANDROID_LOG_DEBUG,"MYAPP","Contents of the file are:",NULL);
while((cont=recvfrom(create_socket, buffer, bufsize, 0,(struct sockaddr *) &address,&serv_addr_size))>0)
{
if(buffer[cont-1]=='*')
break;
memcpy(qBuff+r,buffer,cont);//copying received data to a circular queue
r=(r+3000)%Q_SIZE;
__android_log_print(ANDROID_LOG_DEBUG,"MYAPP","Bytes received:%d",cont);
//write(1, buffer, cont);
}
__android_log_print(ANDROID_LOG_DEBUG,"MYAPP","EOF",NULL);
free(qBuff);
close(create_socket);
}
The above code works fine for a rooted device, but not on an unrooted one. Since the application that i'm creating should be able to run on both rooted and unrooted devices, i need to make the code run on an unrooted device also.
The server was able to connect to the rooted device only after diabling the Linux firewall using /sbin/services iptable stop. So is there a firewall for unrooted device which is blocking the communication port. In the above code i'm trying port no 15000. However i have also tried for other ports also but did'nt workout.
So i kindly request the readers to provide useful answers or reference links for the same. Thanks in advance.

Categories

Resources