Wanted to stop a thread doing some downloads.
The code below work fine when i only have the stopNow = true; and no blocking occur.
I create the boolean stopNow = false; as a field in my IntentService.
Since stopNow only work when the connection is ongoing in the while loop
but it does not work if f.ex connection stales and start to block.
I wanted to add this code to really stop the blocking.
if(socket != null){
socket.shutdownOutput();
socket.shutdownInput();
}
The question is if this is asynchronous so if the execution is ongoing in the
while loop the stopNow = true; will stop it and i can put a sleep(5000) after the stopNow = true; and then the if(socket != null) will be true only if the stopNow had no effect.
hope you follow me..
BroadcastReceiver that are located inside the run():
private class MyIncomingListener extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(Consts.COM_CARLSBERG_STOPOUTGOING)) {
String b = intent.getStringExtra(Consts.COM_CARLSBERG_BATCHUUID);
if(b != null){
if(b.equals(batch.batchUuid)){
stopNow = true;
// sleep(5000) wait for stopNow to take effect
// if socket=null then stopNow did it's job
// if socket is alive then there is blocking to unblock
try{
if(socket != null){
socket.shutdownOutput();
socket.shutdownInput();
}
} catch (Exception e) {}
}
}
}
}
}
this is actually working good so far
stopNow = true;
try{
if(socket != null){
socket.shutdownOutput();
socket.shutdownInput();
}
} catch (Exception e) {}
public final void stop ()
Since: API Level 1
This method is deprecated.
because stopping a thread in this manner is unsafe and can leave your application and the VM in an unpredictable state.
Requests the receiver Thread to stop and throw ThreadDeath. The Thread is resumed if it was suspended and awakened if it was sleeping, so that it can proceed to throw ThreadDeath.
try {
int waited = 0;
while(_active && (waited < _splashTime)) {
sleep(100);
if(_active) {
waited += 100;
}
}
} catch(InterruptedException e) {
// do nothing
} finally {
finish();
Intent intent= new Intent(SplashActivity.this,LoginViewController.class);
startActivity(intent);
stop();
}
Related
I'm trying to implement a way to listen to a client's connection event on the smartphone hotspot. I see that android.net.wifi.WIFI_HOTSPOT_CLIENTS_CHANGED is no longer avaible. How can i do this? I think that this is possible because the smartphone notify me when i client make a connection to the smartphone hotspot.
You can't use the Intent Action...You have to use a custom method, i'l suggest you create a background thread that checks/reads the I.P table (/proc/net/arp) constantly and update you...here's a snippet I've used.
Read i.p list table
public ArrayList<String> getConnectedDevices() {
ArrayList<String> arrayList = new ArrayList();
try {
BufferedReader bufferedReader = new BufferedReader(new FileReader("/proc/net/arp"));
while (true) {
String readLine = bufferedReader.readLine();
if (readLine == null) {
break;
}
String[] split = readLine.split(" +");
if (split != null && split.length >= 4) {
arrayList.add(split[0]);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return arrayList;
}
Create runnable to check
class CheckHotSpotConnection implements Runnable {
private CheckHotSpotConnection() {
}
public void run() {
int i = 0;
while (discoverClient()) {
i = getConnectedDevices().size();
if (i > 1) {
//client discovered
//disable client discovery to end thread
} else {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
Start Thread
new Thread(new CheckHotSpotConnection()).start();
I am creating a simple Morse code app. The user can enter in text which is then translated to Morse and flashed in sequence on a new thread. I have implemented a for loop which is used to turn on/off the camera flash to represent the Morse sequence.
The problem is that when the user navigates away from the activity the on pause method releases the camera but i sometimes get the error 'method called after release'. I am not sure how to cancel the thread from running when the camera is released. I have already attempted to use a volatile Boolean value which is checked at the start of each loop iteration but if the loop is cancelled at any other time but the start then it results in an error.
Does anyone have any ideas/suggestions as to how i could solve this problem?
public void flashTranslation(String message) {
int offIntervalTime = 50;
char[] cArray = message.toCharArray();
for (int i = 0; i < cArray.length; i++) {
if (cArray[i] == '.') {
turnOn();
try {
Thread.sleep(50);
}catch(Exception e)
{
Log.d("One", "Two");
}
turnOff();
try {
Thread.sleep(offIntervalTime);
}catch(Exception e)
{
}
} else if(cArray[i] == ' ')
{
Log.d("EMPTY!", "EMPTY!");
try{
Thread.sleep(100);
}catch(Exception e)
{
}
}
else {
try{
turnOn();
Thread.sleep(dash);
}catch(Exception e)
{
}
try{
turnOff();
Thread.sleep(offIntervalTime);
}catch(Exception e)
{
}
}
}
}
The easiest way to do this is canceling the thread protecting against concurrent access via semaphore. Every time you try to flash on the thread, you check if the thread is canceled. Pseudocode:
Semaphore sem;
onPause(){
sem.take();
camera.turnOff();
camera.release();
thread.cancel();
sem.give();
}
thread.run() {
//This should be run before every call to turnOn or turnoff
sem.take();
if(isCanceled()) {
return;
}
turnOn();
sem.give();
}
onResume() {
new Thread.start();
}
When another thread calls closeConnection(), the thread doesn't reach
Log.d("Subscriber", "Client thread has ended.");
Why is this? What is the blocking behaviour of a stream that has been closed? I thought trying to write or flush to it would generate an IOException, but it seems the code is still blocking somewhere. Where? I can't find info on what happens when you interrupt() on a write, or what happens when writing to a closed outputstream.
public void closeConnection() {
try {
this.interrupt();
autoCloseOutputStream.close();
} catch (IOException e) {
Log.w("Subscriber", "IOException when closing stream. Buffer might not have been flushed to client.");
}
}
#Override
public void run() {
Log.d("Subscriber","Client thread has started.");
ByteBuffer pgnAndDataBytes=null;
while(true) {
try {
pgnAndDataBytes=fmsByteBufferSubscriberQueue.take();
} catch (InterruptedException e) {
break;
}
Log.d("Subscriber","Still running thread");
try {
autoCloseOutputStream.write(pgnAndDataBytes.array());
autoCloseOutputStream.flush();
} catch (IOException e) {
break;
}
}
Log.d("Subscriber", "Client thread has ended.");
}
The output is as follows:
Still running thread
Still running thread
Still running thread
Close called.
And nothing more. Where is it blocking and why?
Have a volatile boolean shouldClose that you set to true on closeConnect(). Incorporate the boolean into the condition check of the while loop.
boolean done = false;
while(!shouldClose && !done) {
try{
autoCloseOutputStream.write(pgnAndDataBytes.getInt());
} catch(BufferUnderflowException bue) {
final ArrayList<Byte> remainder = new ArrayList<Byte>(3);
while(!shouldClose && !done) {
try {
remainder.add(pgnAndDataBytes.get());
} catch(BufferUnderflowException ex) {
autoCloseOutputStream.write(remainder.toArray(new Byte[remainder.size()]);
done = true;
}
}
}
}
Maybe the code kind of shows what I'm attempting to do, so I'll start with that
private void getLicenseResults() {
if (licensed && didCheck == true) {
Thread timer = new Thread() {
public void run() {
try {
sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
Intent openStartingPoint = new Intent(
"***.MAINACTIVITY");
startActivity(openStartingPoint);
finish();
}
}
};
timer.start();
}
if (didCheck == false) {
Toast.makeText(Splash.this, "Checking License, Please Wait",
Toast.LENGTH_LONG).show();
Thread timer = new Thread() {
public void run() {
try {
sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
getLicenseResults();
Log.i("LICENSE", "re-checking");
}
}
};
timer.start();
}
}
I ran the license check without trying to loop it before, and it worked except if the checking took more than a couple seconds it skipped over the
if (licensed && didCheck == true)
and the activity just kind of stood and waited without launching my main activity (this check is on the splash screen).
So I want the "if didCheck = true" part to be called only after didCheck is in fact finally true. I'm sure there's an easy solution, but I'm self-taught and I have no experience with loops or callbacks(?).
Thank you for any help!
You are not setting didCheck to true in your second if statement before the call to getLicenseResults
Hi,
In my app im trying to use Thread.sleep(100) to pause my thread, while its backgrounded in order to use less cpu, but it freezes when I open it back up.
I realized that onResume is not being called when I reopen the app.
Any ideas why?
public void onPause() {
pause = true;
Log.d("mSTATE","THREADPAUSE");
}
public void onResume() {
pause = false;
running = true;
Log.d("mSTATE","THREADRESUME");
}
public void run() {
while(running){
while(pause && running){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
while (!pause && running) {
Canvas c = null;
try {
c = sHolder.lockCanvas(null);
synchronized (sHolder) {
doDraw(c);
powerUps();
}
} finally {
if (c != null) {
sHolder.unlockCanvasAndPost(c);
}
}
}
}
Log.d("mState","EndofRun");
}
When you put your thread to sleep you are also blocking the UI thread thus leading to freezing of your application.
You need to check the Threads in Android way for the best performance.
http://developer.android.com/resources/articles/painless-threading.html