Android - Communicate with Bluetooth subsystem (BlueZ) - android

I'm looking for a way to do periodic bluetooth inquiry's from my Android Smartphone (HTC Desire with Android 4.0.1). The Device is rooted and it is a custom Rom installed so that I have full privileges.
I already wrote a shellscript, which uses hcitool, hciconfig and hcidump to do the inquiry's. That works fine so far, but it is a little to slow for me. I guess that's because of my dirty workaround of using an android-app to execute a shellscript from linux.
Although I got problems by killing the executed processes via my App.
So I'd like to find a way to inquire BT Devices from the Android API.
I found out that there is no possibility 'til now to do this, but i read about the bluez API which is possibly able to fit my requests.
Does anyone have any links, tips or advises for me?
I haven't found anything useful :/
Thanks in advance.
Edit (2012-09-28):
Okay, I think I'm a little closer to the solution now.
I downloaded the source of blueZ library from: bluez.org
Then i put the important files (hci.h, bluetooth.h, hcilib.h and their sourcefiles) into the jni folder of my android project and compiled them into my shared library.
I wrote a JNI Wrapper around the function
hci_inquiry(int dev_id, int len, int nrsp, const uint8_t *lap,inquiry_info **ii, long flags)
and followed the advises of this book to do my inquiry. Everything fine 'til here.
But when I start the inquiry, the function
dev_id = hci_get_route(NULL);
always returns -1, and I can't continue.
Bluetooth is activated, and i already tried to grant root access to my application. Not better :(
Anything I did wrong until here? Isn't it allowed to use BlueZ HCI commands from a android app?
I mean JBlueZ doesn't do anything else is it?
My native code looks like this:
inquiry_info *ii = NULL;
int max_rsp, num_rsp;
int dev_id, sock, len, flags;
int i;
char addr[19] = { 0 };
char name[248] = { 0 };
dev_id = hci_get_route(NULL);
if (dev_id < 0 ) {
LOGI("ERROR ON finding Device ID");
return;
}
sock = hci_open_dev( dev_id );
if (sock < 0) {
LOGI("ERROR ON opening socket");
return;
}
len = 8;
max_rsp = 255;
flags = IREQ_CACHE_FLUSH;
ii = (inquiry_info*)malloc(max_rsp * sizeof(inquiry_info));
num_rsp = hci_inquiry(dev_id, len, max_rsp, NULL, &ii, flags);
//##################################################################################
LOGI("INQUIRY Executed!!!");
(*env)->CallVoidMethod(env, obj, callBackID, num_rsp);
free(ii);
close(sock);
Thank you for any help.

Related

Flutter/Dart UDP multicast send from iOS not receiving on Android

With this setup, I've been able to get two android phones to send and receive UDP broadcasts. I can also use this setup to send a UDP broadcast from a physical Android device to an iPhone.
However, my problem is that it doesn't seem to work the other way around. The send function is ran on the iPhone, and the receive function is being run on the Android phone. The Android phone never gets the broadcast. It seems like something is wrong with the iPhone's sending function. Here's the setup:
The Android side that has worked for me before:
const port = 37069;
const address = '224.0.0.1';
void receive() async {
final socket = await RawDatagramSocket.bind(address, port);
socket.multicastHops = 1;
socket.broadcastEnabled = true;
socket.writeEventsEnabled = true;
socket.listen((RawSocketEvent event) {
print("still listening...");
final packet = socket.receive();
print("The packet was $packet");
print("It came from ${packet?.address}");
});
}
and this is the iPhone side, that seems to be the problem. I'm not getting errors, so I'm wondering if there are any permissions in the Info.plist file that need to be added?
void broadcast() {
// for the iphone
RawDatagramSocket.bind(address, port).then((RawDatagramSocket socket) {
socket.multicastLoopback = false;
socket.broadcastEnabled = true;
socket.readEventsEnabled = true;
for (int i = 0; i < 150; i++) {
socket.send("Sent #$i".codeUnits, InternetAddress(address), port);
print("sent $i");
}
socket.close();
});
}
I've tested this same setup in my project, and it has worked in the following situations:
Android -> Android
Android -> iOS
but, iOS -> Android doesn't work. When I run the app, I can see that the iPhone is indeed sending the data, but the Android isn't receiving anything. Is the Android side the problem? What am I doing wrong?
I ended up using a package called Bonsoir to achieve what I wanted to.
It lets you broadcast and receive network services, and I'm pretty sure its the same underlying technology as household programs like Airplay and Google Casting. It's also very reliable and simple to use.
To send a certain string, I passed in a string argument in the form of a dictionary into the attributes attribute within the BonsoirService class.
The package can be found here.

Native network-related functions randomly blocking in android

I have a library written in C that I'm using from an Android application. I discovered that the application blocks sometimes while executing various functions (what is common is they are all related to networking).
I'm testing on a real Android device running Android 6.
The library is compiled with NDK version 21.
So far I have observed this behavior with 3 functions - getaddrinfo, poll and socket:
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
getaddrinfo(hostname, port, &hints, &result);
////
struct pollfd wait = {
.fd = fd,
.events = event,
.revents = 0
};
status = poll(&wait, 1, 10000);
////
fd = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
These functions are called several times each after the program starts running. The same call can work fine one time and block indefinitely (at least several minutes) the next time. The internet connection on the device seems to be fine.
Any ideas? How can I even approach debugging such a problem?
I didn't actually find the reason for the problem, but I found how to fix it. Part of the code was written by somebody else and I wasn't sure what exactly it was doing. After rewriting this part, everything started to work fine.
Among other things, the code was spawning a new process with fork(). I suspect the problem to be related to that.

Latest android no longer sends UDP broadcast packets

So we have been running the following code on android (Samsung Note 4) and iOS with out trouble until the latest phones started coming out with android 7+ (Samsung S8, OnePlus3T). We would send out our broadcast to identify other systems that would respond to this message. Now we find that UDP is blocked on the phone.
We have used Evothings to test that UDP is blocked. Programmatically I don't think I am missing anything to make this work.
We have noticed a change with the way WiFi works on android. If the WiFi connection doesn't have internet, the system seems to behave differently.
chrome.system.network.getNetworkInterfaces(function (networkIfaceArray) {
for (var i = 0; i < networkIfaceArray.length; i++) {
var iface = networkIfaceArray[i];
if (iface.prefixLength < 32) {
addr_array = parseIP(iface.address);
mask = 32 - iface.prefixLength;
mask = Math.pow(2, mask) - 1;
pointer = 3;
while (mask > 255) {
addr_array[pointer++] = 255;
mask -= 255;
}
addr_array[pointer] = mask;
udp_sock.send(app.socketId, message,
addr_array.join("."), 5000, function (sendInfo) {
//check for response
});
}
}
});
We have tried this answer where they suggest different ports. Most of the posts here are older than version 7 and so don't address our problem.
Again, it still works with the older versions of android and iOS. If you have come across this problem please share.
You should try to use the setBroadcast() function. Old versions of the cordova plugin did not have it implemented, see https://github.com/MobileChromeApps/cordova-plugin-chrome-apps-sockets-udp/issues/7, so you may have to check if it is defined before using it. Possibly the Evothings app uses an older version of the cordova plugin. Maybe the newer Android devices default the broadcast option off, so calling setBroadcast() should allow it to work.
// Set Broadcast (if available)
if (chrome.sockets.udp.setBroadcast != undefined) {
chrome.sockets.udp.setBroadcast(app.socketId, true, function (result) {
if (result < 0) {
console.log("setBroadcast failed");
}
else {
console.log("setBroadcast worked");
}
});
}

Accessing /dev/input/events0 file through jni in Android 4.2

I need to port an automation tool from Android 2.3 to Android 4.2 based target. I am trying to get some touch events from /dev/input/events0 using open() system call and then use a poll() system call to wait for any changes on its file descriptor.
This works just fine if I write the logic in a C file and run the binary by placing it in system/bin directory. poll method returns and I can read the content using read() method on the descriptor.
I call these methods using JNI in Android 2.3 based target. It works fine, but only if the app is a part of the system image and the library(native code) exists in system/lib directory as a .so file.
But now the problem is, the same code is not running in Android 4.2. The poll() system call never returns, even if I give a lower timeout value.
One important point to note here is, this same behavior was observed when the library existed as a part of the APK file in Android 2.3 and was run as an installed application.
Also currently I have only quick boot build working, no normal boot. APK/ODEX and *.so files is what I have at my disposal.
I am suspecting it is an issue with permissions. Internally android is not giving me access to driver files in 4.2, as application seems to be better sandboxed than it was in 2.3. Ironically, open() works just fine, only when I do poll(), it is not working.
I need to overcome this problem. Please help.
Here is code snippet:-
int i, numread, value, ret, readlen;
struct input_event event;
struct timeval now;
struct timespec tm;
while (run) {
/* wait for input from any of the input devices(/dev/input/events0) */
if (poll(input_fds, NUM_DEVICES , -1) < 0) {
return EVENT_RECORDER_ERROR;
}
__android_log_print(ANDROID_LOG_INFO, "EVENT_RECORD",
"Poll completed");
for (i = 0; i < NUM_DEVICES; i++) {
__android_log_print(ANDROID_LOG_INFO, "EVENT_RECORD",
"device no %d", i);
if (input_fds[i].revents & POLLIN) {
if (input_fds[i].fd == sockfd)
readlen = MAX_DATA_LENGTH;
else
readlen = sizeof(event);
/* read the data here and write it to the output file */
numread = read(input_fds[i].fd, buffer, readlen);
}
}
}

did anybody use ACR1222L android library?

I am writing an app which will be run in tablets. The tablet will be connected to ACR1222L NFC reader.
I am using their android library to interact with the reader. I can detect the USB reader and also can read the readers name.
BUT i am struggling to read data from NFC tag. In fact I have no clue where to start, which classes/methods to use.
Is there anyone who already worked with ACR1222L and its android library?
Some guidelines, sample code, tutorial would save my life.
EDIT:
Well, I got little smarter now, I can read the UID. this is how to do it.
#Override
protected void onCreate(Bundle savedInstanceState) {
............... your code
mReader = new Reader(mManager);
mReader.setOnStateChangeListener(new OnStateChangeListener() {
#Override
public void onStateChange(int slotNum, int prevState, int currState) {
//This command is for the card UID
byte[] command = {(byte) 0xFF,(byte) 0xCA,0x00,0x00,0x00};
byte[] response = new byte[300];
int responseLength;
if (currState == Reader.CARD_PRESENT) {
try {
mReader.power(slotNum,Reader.CARD_WARM_RESET);
mReader.setProtocol(slotNum, Reader.PROTOCOL_T0| Reader.PROTOCOL_T1);
responseLength=mReader.transmit(slotNum,command, command.length, response,response.length);
//Here i have the card UID if i send the proper command
responsedata=NfcUtils.convertBinToASCII(response);
}
}
}
BUT I am still struggling to read the payload from the tag. I have also look into nfctools library. But I don't know where to start. Would be great if anyone guide my through the library.
Yes, this is possible - and quite the same as working with the ACR 122 as the API is almost identical.
I've developed a (commmercially available) library which probably does most of what you're looking into, or can serve as a starting point for your own implementation.

Categories

Resources