Android: Thread infinite loop / phone overheating - android

I'm working on a Thread that handles all server connections:
public void run() {
//this initializes Socket and PrintWriter/DataInputStream
connect(server, port);
while(true) {
//queue is a BlockingQueue where I put the messages to send
while(!queue.isEmpty()) s
//COMMUNICATE-WITH-SERVER-CODE
}
}
}
The code works, but after a minute or so, my phone starts overheating and battery goes down fast. I know it's because of the infinite loop.
How can I solve it? I want a Thread which, once started, keeps the connection to the server (so that DataInputStream and PrintWriter won't be initialized every time). And I want the thread to be responsive: when I click a Button it should sent instantaneously a message to the server for processing.
I have implemented a Handler for communicating Thread->Activity. But how can I communicate Activity->Thread?
Any tip would be welcome.

Generally the solution would be to add a polling intervall, ex: sleep the thread for 500ms after each iteration. But in this case there is no need for that, because we do not have to poll a BlockingQueue. From the doc
A Queue that additionally supports operations that wait for the queue to become non-empty when retrieving an element, and wait for space to become available in the queue when storing an element.
If we use a BlockingQueue, then the queue.pop() call blocks if the queue is empty and remains blocked until an entry is pushed onto the queue. There fore there is no need for looping.
However, we will need to have some sort of mechanism to keep the thread from terminating. Here is a simple example:
public void run() {
try {
while (true) {
handleServerIO(queue.take());
}
}catch (InterruptedException ex) {
... handle ...
}
}

Related

Is using Executors.newSingleThreadExecutor recommended in app widget

Currently, in my main app, I am sending multiple texts to status bar object.
My status bar object, is going to display multiple texts sequentially, with sleep time of N seconds for each display interval.
Here's my implementation in my main app.
public synchronized void setNextText(final CharSequence text) {
if (executor == null) {
executor = Executors.newSingleThreadExecutor();
}
executor.execute(new Runnable() {
#Override
public void run() {
Fragment fragment = getTargetFragment();
if (fragment instanceof OnStatusBarUpdaterListener) {
((OnStatusBarUpdaterListener)fragment).setNextText(text);
try {
// Allow 1 seconds for every text.
Thread.sleep(Constants.STATUS_BAR_UPDATER_TIME);
} catch (InterruptedException ex) {
Log.e(TAG, "", ex);
}
}
}
});
}
Now, I would like to have the same behavior in app widget. I was wondering, is using Executor being recommended in app widget environment? If not, what class I should use to achieve the similar objective?
I do have experience in using HandlerThread + AlarmManager in app widget. It works good so far. However, the operation done by the runnable is one time. It doesn't sleep and wait.
The following is the code which I use to update stock price in fixed interval.
// This code is trigger by AlarmManager periodically.
if (holder.updateStockPriceHandlerThread == null) {
holder.updateStockPriceHandlerThread = new HandlerThread("updateStockPriceHandlerThread" + appWidgetId);
holder.updateStockPriceHandlerThread.start();
holder.updateStockPriceWorkerQueue = new Handler(holder.updateStockPriceHandlerThread.getLooper());
holder.updateStockPriceWorkerQueue.post(getUpdateStockPriceRunnable(...
}
However, I have a feeling that, for use case "display multiple texts sequentially, with sleep time of N seconds for each display interval", AlarmManager might not be a good solution. Imagine I have 100 texts. Having to set 100 alarms for 100 texts doesn't sound good...
An AppWidgetProvider is a subclass of BroadcastReceiver. Once your callback (e.g., onUpdate()) returns, your process can be terminated at any point.
If that is not a problem — if you fail to finish the semi-animation that you are doing, that's OK — using an Executor from onUpdate() could work.
If you want to make sure that the text changes go to completion, delegate the app widget updating to a Service, where you use your Executor. Call stopSelf() on the Service when you are done, so it can go away and not artificially keep your process around.
Well the singleThread instance work creates an Executor that uses a single worker thread. meaning only thread to process your operation. But in you case use at least two. Your operations sounds expensive.
To conclude your question stick with the executor service as it thread safe.

Queue Android Gatt operations

I made a app the connects to a ble device and receives data from it. I was following this link "http://toastdroid.com/2014/09/22/android-bluetooth-low-energy-tutorial" at the Hints and observation section it says to Queue All GATT operations. How do I do that?
Check out NordicSemiconductors open source project Puck Central, or more specifically the GattManager class, who perfectly demonstrates how to queue all GATT operations.
If you don't want to handle this sort low level bluetooth specifics yourself however, I can recommend the great library RxAndroidBle, which does much of the heavy lifting for you.
To queue the requests you could make a queue class which has an Arraylist of requests.
Every time you want to make a request add it to the queue and start processing the queue (if the queue isn't already being processed). Once you've processed the current item check if there are still items to process and carry on processing them.
You'll also probably need to add a timeout in case one of the requests gets stuck.
Sample code on how you could process a queue using a handler:
private void startProcessingQueue() {
if (queueIsRunning) {
return;
}
queueIsRunning = true;
h.postDelayed(new Runnable(){
public void run(){
processQueue();
if(queue.isEmpty()) {
queueIsRunning = false;
return;
}
h.postDelayed(this, QUEUE_PROCESSING_DELAY);
}
}, QUEUE_PROCESSING_DELAY);
}

Service Uses Increasingly More Memory

I have a service on the app which needs to run indefinitely - even when app is closed. It's going to ping a network source, if a state changes then the service must trigger a notification. The loop triggering the pings in the service is user chosen, with the smallest value of 5000ms (5 Seconds). I have the pings on a separate thread (off the UI thread) with calls to a handler thread to post toasts (temporarily while programming) to the UI thread.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast successMessage = Toast.makeText(this, "Service Started", Toast.LENGTH_SHORT);
successMessage.show();
//sendToastOnUIThread(1000);
new Thread(new Runnable(){
public void run() {
while(true) {
try {
Thread.sleep(GLOBAL_PING_TIMER);
} catch (InterruptedException e) {
e.printStackTrace();
}
sendToastOnUIThread();
//Code for pings here...
}
}
}).start();
return START_STICKY;
}
Above you can see my onStartCommand from the service - when testing this, I only used the code above and left out my code to ping the network source etc.
Incase you wonder whats in 'sendToastOnUIThread();'
public void sendToastOnUIThread(){
Handler h = new Handler(AutoPingServerService.this.getMainLooper());
h.post(new Runnable() {
#Override
public void run() {
Toast.makeText(AutoPingServerService.this,"Servers Pinged",Toast.LENGTH_SHORT).show();
}
});
}
So when this service is running, I get the toasts every 5 seconds, but the service memory just keeps stacking up (seems to cap at 8.5mb) but starts off around 1mb and just builds up around 0.1mb per loop. Am I making too many threads somehow? There should only be the UI thread, the new thread to handle the pings and the handler thread to post toasts when I need them (this will be replaces with notifications once it works)
Open to ideas - fairly new to android development, I wouldn't be surprised if i'm using all the wrong thread types. Possibly this is normal?
EDIT: Spelling.
Okay update for anyone curious:
The memory does get wiped after a while (pweh) as you'll reach a terminal capacity. Not sure if this is ideal but hey - I'm not going to sell it for millions, if the app crashes, I'll update this post. Don't fix what's not broken eh?
Anyway - #Deev kindly said I should move to an IntentService, I did not. I possibly will in the future, but this method works (Although it does look simpler to use a IntentService).

Android TextView text updation on receiving data from Inputstream

I am coding a client-server app to test communication between two Android Bluetooth devices. On my client, I am reading data from the inputstream object.
When I checked by printing on the logcat, the data is being read successfully. However when I try to set the data to a TextView, it is not displaying.
In the following code, packetsReceivedTV is the TextView object. I am getting correct output when I print 'result' on logcat, but the text is not setting in the TextView. Is it because I am setting the text in a while (listening) loop?
while(listening){
bytesRead =instream.read(buffer);
if(bytesRead!=-1){
String dataRead= new String(buffer,"UTF-8");
System.err.println("*************result : "+dataRead);
packetsReceivedTV.setText("Received : "+dataRead);
packetsReceivedTV.invalidate();
}
}
Even a call to invalidate() is not working.
NOTE: Occasionally when I kill the server process on one device, then the TextView on the client device updates correctly. But this does not happen always. Please help!
It's not clear which thread your code is called on, but you need to make sure these two operations are happening on different threads:
The stream polling needs to be done on a background thread. If you are not doing this, then you are not seeing text because the thread blocking on read() keeps the main thread from updating the UI elements.
The setText() method call must happen on the main (UI) thread. If you are not doing this, the text will also not display--and on some devices you will even see crashes.
I'll assume this code live in an activity (since you are trying to update UI elements). While this is not the best practice, a simple example that demonstrates the concept follows:
Thread pollingThread = new Thread() {
#Override
public void run() {
…
//This code needs to be running on a background thread
while(listening){
bytesRead = instream.read(buffer);
if(bytesRead != -1){
String dataRead= new String(buffer,"UTF-8");
System.err.println("*************result : "+dataRead);
runOnUiThread(new Runnable() {
#Override
public void run() {
//This code needs to be posted back to the main thread.
packetsReceivedTV.setText("Received : "+dataRead);
}
});
}
}
}
};
//Start the listener thread
pollingThread.start();
This is really just meant to illustrate the basic point that the polling code must be in the background and the view code must be on the main thread.
Even a call to invalidate() is not working.
TextView calls this internally when its contents change, so you calling it is redundant.

pthread_unlock_mutex doesn't wake up waiting thread

I have two threads, one thread run an loop to check if there is data received by wait on multiple sockets, and another thread try to add an socket to the socket list or remove one.
The code is as following:
Thread 1:
while (!stop)
{
// usleep(0)
AutoLock lock(_socketsLock); // AutoLock will call pthread_lock_mutex/pthread_unlock_mutex.
Socket* activeSockets = waitOnSockets(_sockets, 50); // Wait 50ms for data on the socket list.
// Handle the data from socket.
}
Thread 2:
void AddSocket(Socket* socket)
{
AutoLock lock(_socketsLock);
_sockets.push_back(socket);
}
The problem is AddSocket seams cannot got the lock in a long time on Android system, I have run the application on Mac, seams the AddSocket wait at most for one loop, but on android it can be 10+seconds.
So I assume the pthread_unlock_mutex doesn't wake up other waiting thread on Android. I can add usleep(0) in the begin of the loop to resolve this issue, even man page of usleep say usleep(0) will be no effect.
But if i add usleep(0) there will always thread switch for each loop, which I think will not be good for mobile device performance.
So what's the alternative way to release CPU when call pthread_unlock_mutex and doesn't case performance issue, in another word only release CPU when there is thread waiting for the lock?
How about:
Thread 1:
while (!stop)
{
AutoLock addLock(_addLock);
AutoLock socLock(_socketsLock);
// Release the addLock here.
// This gives thread 2 an opportunity to get the first lock while this
// thread is waiting on the socket.
AutoRelease addRel(addLock);
// When this thread finishes it will be forces to sleep if there are
// any waiting AddSocket requests otherwise it will continue as normal.
Socket* activeSockets = waitOnSockets(_sockets, 50);
}
Thread 2:
void AddSocket(Socket* socket)
{
AutoLock addLock(_addLock);
AutoLock socLock(_socketsLock);
_sockets.push_back(socket);
}

Categories

Resources