Ausche Ausche - 5 months ago 14
Android Question

Thread within service dies for some reason*

I've posted about this project before, I'm trying to create a service, from a

Home
Activity
, that constantly checks if the screen is locked or not (
ScreenLockService
is the
IntentService's
name). If so, it creates another service to "listen" (
Listener
is the
IntentService's
name) for sound. If not, it stops the existing
Listener
service if one is running.

So to do so, I've created a
Thread
within the
onHandleIntent
method of
SLS
that should always be checking if the screen is locked or not. Here is how that's implemented so far:

(Sorry for the wall of code, I'll try to make it look pretty)

Thread checkScreen = new Thread(
new Runnable() {

@Override
public void run() {

Boolean lockInput = false;

while(!Thread.interrupted()) {

//The first time the screen becomes locked is special, it should start the whole process from there
KeyguardManager firstKeyManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);

if (firstKeyManager.inKeyguardRestrictedInputMode()) {
lockInput = true;
}

//If the screen has been locked for the first time:
while(lockInput) {

//Put a timer here do slow the app down and figure out what's going wrong
new Timer().schedule(
new TimerTask() {

@Override
public void run() {

//if the screen is locked start listener service else stop listener service (METHODS WITHIN THIS SERVICE HANDLE THIS)
KeyguardManager secondKeyManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);

if (secondKeyManager.inKeyguardRestrictedInputMode()) {
startListener();
}
else if (!secondKeyManager.inKeyguardRestrictedInputMode()) {
stopListener();
}
}
}, 10000 //10 seconds
);
}
}
}
}
);



//Might be relevant to the problem, if the thread dies I need it to start back up again.
//This is part of the onHandleIntent method, at the very bottom, and not inside the thread.
checkScreen.setName("checkScreen");
Log.d(TAG, "Starting SLS thread");
checkScreen.start();
checkScreenAlive = true;

while(checkScreenAlive){
if(!checkScreen.isAlive()){
Log.d(TAG, "Restarting check screen!");
checkScreen.start();
}
}


Now, I have
Log
messages all over the place so I can see what state the app is in (starting services, stopping services, checking the screen, listening, etc). When I debug it and lock the screen for the first time, nothing will be logged until 10 seconds later it spams
Listener Service already running
about 20 times then the service dies.

Maybe I don't fully understand how the timer works in java, but I have no clue why the service is dying. I probably don't even need to do this in a thread, or maybe not even use an
IntentService
and use a regular
Service
instead. I've read about the differences and I think what I have is right.

If I should post more code I can, don't hesitate to ask. I'm trying to make this as straightforward as possible, this is my first app and I'm still easily confused by some of this stuff.

Answer

You have while(lockInput) { which never gets set to false and will generate a lot of Timer().schedule events.

This schedule will be kicked after 10seconds which is where you are seeing the delay.

I would start by changing

while(lockInput) { 
...
}

to

if(lockInput) {
    lockInput = false; //Only want this called once per check

    //Put a timer here do slow the app down and figure out what's going wrong
    new Timer().schedule(
        new TimerTask() {

            @Override
            public void run() {

                //if the screen is locked start listener service else stop listener service (METHODS WITHIN THIS SERVICE HANDLE THIS)
                KeyguardManager secondKeyManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);

                if (secondKeyManager.inKeyguardRestrictedInputMode()) {
                    startListener(); 
                } 
                else if (!secondKeyManager.inKeyguardRestrictedInputMode()) {
                    stopListener();
                }
            }
        }, 100 //Fire of the check almost instantly
    );
}

Thread.sleep(10000); //So we are yeilding to the system, don't want an essential while(true) loop
Comments