I'm currently trying to assess whether a project can be realised for Android. One major problem I see it that, since it's a P2P client, we'd have to keep a considerable amount of connections open when running. Now the connections do not transfer large amounts of data, it's more of a messaging system, so having a thread for each connection creates a useless overhead if we're reading a single message of 64 bytes every now and then.
So I was wondering whether there is support for non blocking IO such as select() or poll() on Linux.
Any suggestion?
Check out java.nio Sockets, Selectors, and Channels. Some links:
Android: Unbuffered IO
http://developer.android.com/reference/java/nio/channels/ServerSocketChannel.html
http://developer.android.com/reference/java/nio/channels/SocketChannel.html
http://www.developer.com/java/article.php/3837316/Non-Blocking-IO-Made-Possible-in-Java.htm
Or, maybe I didn't read your question right.
Of course. Once your application declares uses internet permission, you can do all normal linux networking things normally available to a non-root user in C using the NDK, and any of them from java that someone (possibly you if no one beat you too it) has bothered to write support for.
Well, one exception: your mobile provider probably won't permit incoming connections, and neither will most wifi routers unless you specially set them up to. But those are infrastructure issues rather than issues with android itself.
You will probably also need to come up with some combination of an Activity to provide the foreground UI and a Service to continue the actual transfers in the background with just a status bar icon showing.
Related
Curl version: 7.71.0 with c-ares
Background
We are building a library that's being integrated into mobile apps. We are targeting both iOS and Android.
Curl initialisation happens in a static block inside the library.
The iOS version of the library is bundled into a framework, which is loaded at app startup, if i'm not mistaken.
The Android version of the library is bundled in a module, which is lazily loaded. (I know this is an issue, especially since we link against OpenSSL, but it's probably important for context).
We built a small HTTP client with curl, that allows use to download some data blob from trusted servers.
Quick architecture review
The HTTP client is running on its own thread. It holds a curl_multi_handle, and any transfer started append a curl_easy_handle to it, and return a handle to a Response that contains a buffer to read the received bytes from, and is used to control the transfer if needed.
Since cURL handles are not thread safe, any action (referred to as Tasks from now on) to the handle is dispatched to the HTTP client's thread, and a boost::shared_future is returned (we might want to block or not depending on the use case).
Here is a rough idea of how the main loop is structured:
while (!done) {
deal_with_transfer();
check_transfer_status();
cleanup_any_orphan_transfer();
execute_all_queue_tasks();
curl_multi_poll(multi, nullptr, 0, very_large_number, nullptr);
}
Appending to the task queue also performs a curl_multi_wakeup(multi) to make sure that task is executed (e.g. adding a new download is also a dispatched task).
The issue
We've only thus far tested on Android, and we've seen in some cases, HTTP client tasks that are blocking are sometimes never returning.
Logs and stacktraces show that we wait on a task being executed on by the HTTP client, but the client is still polling. Everything seems to indicate that it was't woken up when appending a task.
I can't seem to replicate the issue locally, on a device, but it happens often enough to be a blocker issue.
I'm a bit at a loss here, and I don't really know where to start looking to find a way to reproduce the issue, let alone fixing it.
I hope I gave enough context to start making educated guess, or even find a the source of error!
Thanks for reading!
Limitations on network activities for background processes
Mobile operating systems such as Android and iOS have a different scheduling strategies for background processes compared to traditional *nix operating systems. The mobile OS tends to starve the background processes in order to preserve the battery time. This is know as background process optimization and will be applied to the processes/threads of the application the moment application enters in background.
As of Android 7, the background processes are no longer informed about the network events with the CONNECTIVITY_ACTION broadcasts unless they register in the manifest that they want to receive the events.
Although the lobcurl is used in android native code, the threads created from the native library will be subject of the entitlements that the application declared in the manifest (which need to be granted).
Workaround to try
I know how frustrating a blocking issue can be so I can offer you a quick workaround to try until the problem is resolved.
curl_multi_poll() can receive a timeout that in your code is set to a very_large_number. In addition, the last parameter of the function call is a pointer to an integer numfds that will be populated with the number of file descriptors on which an event occurred while the curl_multi_pool() was pooling.
You can use this in your favor to construct a workaround in the following way:
Make the very_large_number a reasonably_small_number
replace the nullptr with &numfds
Surround the curl_multi_poll with a do ... while loop
So you will have something like this:
int numfds;
while (!done) {
deal_with_transfer();
check_transfer_status();
cleanup_any_orphan_transfer();
execute_all_queue_tasks();
numfds = 0;
do {
curl_multi_poll(multi, nullptr, 0, reasonably_small_number, &numfds);
numfds += check_for_other_conditions();
} while ( numfds == 0 );
}
Select the timeout to be a reasonable number (ex. 1s, 10s, 60s ...) that will allow you to break the pooling forcefully, at the same time, not to drain the battery.
I am adding the check_for_other_conditions() so you can use is to check additional conditions. By example the size of the task queue, assuming that there are situations in which the curl_multi_poll() can miss an event, although the event occurred, this extra check can help to break the loop and start executing the tasks.
If two (or more) devices are connected to the same network, and each has my apk installed, how might one device efficiently 'talk' to the other? Google Play services, Wifi Direct, and bluetooth is unfortunately not available on these devices.
I thought of using a 3rd party push notification service, but ideally I need the response between either device to be as fast as possible, and long-lived.
I have managed to get two devices sending messages to one another using the old client-server Network Discovery Sample app in the docs. However, if either of the apps is closed or leaves memory, the connection is obviously broken. Therefore I'm trying to figure out if this is possible through a Service, which I understand exists outside of the Activity lifecycle.
I understand how an Activity might connect to a Service to send a message (good sample on that located here), but from what I gather this all happens locally on the device. Is it possible to have this exchange happen over a local network, from one app to another? I guess what I'm saying is how can I set up a basic client server socket relationship between two apps that won't die?
It has been a long time but it should still work.
The problem here, as I understand it, is to have something that keeps running when the app is gone.
I remember using IntentService for this purpose. In the onHandleIntent() we made it loop while(!stopCondition) {...}
It was a stable solution then but it was around kitkat's time.
I'd try with the solution in your first paragraph being executed and managed by the IntentService which should keep it available.
I am looking for options around creating a multi-platform application that will react to a HTTP call made to it. To explain my situation:
I have software running on client machines which is capable of making HTTP requests, specifically passing information via GET;
I can adapt the software to accept a manually inputted IP address and any other information (such as authentication tokens) but not really change the comms method;
The requirement is that this software can pass small amounts of information, on the fly, to an app running on a smartphone;
I'm able to specify networking restrictions, such as being on the same local network etc;
It's not really viable for me to create a server to sit between the app and the client.
My thinking is that I could create a simple app to effectively act as a server, sitting and listening for a HTTP call and acting on the information passed to it.
Phonegap crossed my mind purely for the cross-platform capability; Ultimately, if it needed to be native development, whilst not preferred, it is an option.
Everything I've found on the subject thus far is either specific to a platform, usually with no alternative on competing platforms, or is reliant on the app as a client or an intermediary server handling the connections.
My question is, is such a thing - effectively setting up an iPhone or Android device as a server with a listening port - actually possible in Phonegap, or at all?
I appreciate that there are some (very valid) security concerns with the above approach - additional controls will be put into place to deal with that, right now I'm at the beginning of the search and looking to see which is the most viable way forward.
I would have to say that your approach is a bad idea. You have to keep in mind that the OS can kill your app if it is in the background any time it feels like it. I would look more into using a push service to send the app any updates. That way, even if the app was killed, when the user opens the app it has the latest info. My 2cents.
As relatively new to the android platform I was given the task of implementing a email client. For this I want to use an service that allways run in the background (client should allways receive emails as soon as the server gets them, requirement from the customer).
Now I've looked into the Service's in android, but can't seem to find any good answer on whether or not the Service should be local or remote.
What would the main advantages/disadvantages be with choosing one over the other? Bare in mind the Service must be running at all times. I know, I know. BAD. But it is essential to core features of the application.
First, the correct/efficient way to do instant notifications from a remote server like this on Android is to use Google Cloud Messaging. GCM lets you remotely wake up the device by sending an Intent to your application, which you can then use as a signal to fetch the message from the server, post a notification to the status bar, etc.
Doing what you're describing with an eternally running service will have a significant effect on battery life unless you get everything exactly right. Keeping the phone awake all the time is not a viable option. Use GCM and do not roll your own solution for this.
But since your question was more general about whether to run a service in a separate process, in general simpler is better and in this case simpler means running in the same process. You'll have access to all of the various elements of your app's process in memory and in general you will probably have a much easier time. Your events will all happen on the same main thread's Looper. Everything will be much more straightforward.
If you don't already have a very good reason for using a separate process for your service, you should run it in the same process.
Generally I don't know the reason why you can want to use another process. If you will - you'll have to deal with Inter-process communications, with all this AIDL, Parcels etc.
And if you will keep the same process - it will be much easier to transfer the data between your components.
The only reasons to make several processes I think is to try to avoid Android Heap budget limitation. You can try to move heavy objects between processes and try to double your limit. However I think you don't need this, also it's bad way too.
So I will recommend not to play with processes and keep things as simple as possible.
Good luck
I'm building a program which interfaces with a device which runs its own internal web server. I communicate with the device via a web API.
Basically what happens is that a GUI is presented to the user, where the user can make certain modifications to the device. These changes are communicated to the device, and results are returned through XML. The device needs to converse with the program in the background more or less continually (say every 15s or so) to update certain values to the user.
My structure that I'm envisioning is something like this:
UI - Main - Networking - XML Parser.
I'm looking for advice on how to manage these. I understand the UI thread should be separate to provide a smooth experience to users. I also understand that the networking should be at least an asynchronous task. I'm not so sure about how to handle their interaction, and make sure things are happening smoothly and effectively.
My idea is that Main will handle passing data around, telling the networker to send specific messages or changes, passing the returned XML to the parser, and then passing the parsed values to UI for handling.
I'm curious though for advice beyond that.
Have a look at creating a service that is created with your Activity. Without knowing the details of your plan, a Service looks like the optimal solution to perform all the heavy work.
UPDATE:
You could have the calls to web API run in a Service and, when needed, update the UI through an interface. You would have to instruct the Service to run on its own thread, so thread safety is an issue, but less trouble in the long run than using an AsyncTask.
Have a thought about using Google C2DM.
In your case,
Pros -> Less battery use, coordinated network traffic, Don't have to run a continues service and doesn't have the potential of being killed when the device runs out of resources.
Cons -> You have to post the results manually back to your internal server, and server should know which request the device is replying to. Communication is disconnected and may not be real-time. Requires a google account on the device and Google market.