Latest android no longer sends UDP broadcast packets - android

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");
}
});
}

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.

How to detect android app is running on Bluestacks emulator

I need to disable app from running on emulators so I somehow combined answers of this question. It's working on most emulators but it can't detect blustacks. I can not find a robust way to detect blustacks as it has most of a real device properties.
I found safeToRun library that using Build.BOOTLOADER == OsCheckConstants.UNKNOWN to detect blustacks but I'm not sure that only this condition is enough to make sure the running device is a blustacks emulator and I'm afraid that some real devices return "unknown" as bootloader parameter.
it is worth mentioning that this block of code can't detect bluestacks too (glGetString returns null)
try {
String opengl = android.opengl.GLES20.glGetString(android.opengl.GLES20.GL_RENDERER);
if (opengl != null) {
if (opengl.contains("Bluestacks") ||
opengl.contains("Translator")
)
newRating += 10;
}
} catch (Exception e) {
e.printStackTrace();
}
any ideas or solutions?

Android differentiate between a TV and a STB

How can I differentiate between a TV and a STB/game console on AndroidTV programatically? This method (https://developer.android.com/training/tv/start/hardware) won't work because an STB running AndroidTV is considered a television.
What's Your Goal?
The obvious reason for doing this would be to determine if a device is suitable for a game to be played on. If it's for any other reason, then the purpose needs to be elaborated on in order to receive applicable assistance.
With that said ...
Since it's not possible to query the device type directly -- personally, I'd look for something that only a game console would be likely to have.
In other words: a game controller/gamepad.
public ArrayList<Integer> getGameControllerIds() {
ArrayList<Integer> gameControllerDeviceIds = new ArrayList<Integer>();
int[] deviceIds = InputDevice.getDeviceIds();
for (int deviceId : deviceIds) {
InputDevice dev = InputDevice.getDevice(deviceId);
int sources = dev.getSources();
// Verify that the device has gamepad buttons, control sticks, or both.
if (((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD)
|| ((sources & InputDevice.SOURCE_JOYSTICK)
== InputDevice.SOURCE_JOYSTICK)) {
// This device is a game controller. Store its device ID.
if (!gameControllerDeviceIds.contains(deviceId)) {
gameControllerDeviceIds.add(deviceId);
}
}
}
return gameControllerDeviceIds;
}
Of course, it's not fool-proof. Obviously, nothing would be returned if the gamepad(s) were unplugged at the time (not sure when that would happen). Not to mention, some TVs support gamepads (Samsung comes to mind first) -- but, if you're intention is to verify that there's an adequate input available for the application, this would be ideal.
If a gamepad isn't present, a message could be displayed stating, "Please connect a gamepad." -- while continuously checking in the background, and automatically proceeding once one is detected.

how to stop my app in Parallel Space?

I created an app. I want my one app only per mobile but i can create clone of my app using Parallel Spaceļ¼Multi Accounts. So my question is how to stop to making clone of my app. Is android have any unique identifier, which is not alterable even if user reset the phone?
I think there is not a way to prevent "Parallel Space" to clone your app, that is something related with android system.
A simple workaround I use is to check whether the Parallel Space app is installed(ps package name: com.lbe.parallel.intl).
public boolean isAppInstalled(String packageName) {
try {
getPackageManager().getApplicationInfo(packageName, 0);
return true;
}
catch (PackageManager.NameNotFoundException e) {
return false;
}
}
As you can guess it is not reliable since many different apps can be used for this purpose. I didn't go further for my case but one thing that comes to my mind; if you have file write permission you can create a global file and put something there to check while opening your app.
Someone who knows how such apps work can provide better answers. If they are changing something in your apk while copying, then you can check those changes or hashcode of the apk, but it seems that they run your app in a virtual os, so this may not lead to a solution.
And there is not a successful unique id on android unfortunately. That is something I hate about android. I check different identifiers like deviceid, imei, mac address etc.. but parallel space creates new values for all of them.
After I searched a lot for a solution to stop the app cloning, I came across this idea, which is to check the path in which the app data is installed on the phone.
The following code explains the idea further:
int APP_PACKAGE_COUNT = 2; //----> my app package name is com.test.app the number is count of dots in package name
private void checkClonner() {
String path = this.getFilesDir().getAbsolutePath();
int count = getDotCount(path);
if (count > APP_PACKAGE_COUNT) {
throw new RuntimeException("This app does not work in a cloning environment");
}
}
private int getDotCount(String path) {
int count = 0;
for (int i = 0; i < path.length(); i++) {
if (count > APP_PACKAGE_COUNT) {
break;
}
if (path.charAt(i) == '.') {
count++;
}
}
return count;
}

Android - Communicate with Bluetooth subsystem (BlueZ)

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.

Categories

Resources