I have created an app. It starts a service(onStartCommand type).
It creates a thread that keeps on monitor the clipboard:
private class MonitorTask extends Thread {
#Override
public void run() {
mKeepRunning = true;
while (true) {
doTask(); //-this function uses the toast to show the string in clipboard
try {
Thread.sleep(300);
} catch (InterruptedException ignored) {
}
if (!mKeepRunning) {
break;
}
}
}
I found that the after some time passed, the service was still there (according to running service manager), but the thread disappeared. How can I keep the thread running forever until user closes the app.
I guess that may be InterruptedException, how can I use that catch to restart the Thread?
Some old threads mentioned using AlarmManager to "startup the service and do something, close the service" at regular interval, but i dont think it is a good idea?
Please let me know if there is a typical way to do so or any good idea? thanks in advance.
Update
in fact, i know there is ClipboardManager, but i know this one is not compatible to android 2.3.4. Besides, I would like to know if I want to create a thread in service, how can i reset it if it was killed? thanks
The best way to accomplish what you are trying to do is by using the ClipboardManager class, always try to avoid doing you own "Monitoring" functionality specially when it already exist in the OS and make sure if the OS itself already provides a BroadcastReceiver triggering an action with whatever you are expecting, take a look at the documentation for this class:
http://developer.android.com/reference/android/content/ClipboardManager.html
Instead of having a thread running doing nothing, draining battery and performance, why dont you create a BroadcastReceiver waitting for Clipboard actions, make use of the method:
ClipboardManager.addPrimaryClipChangedListener(ClipboardManager.OnPrimaryClipChangedListener what)
to be notified of any changes...
Regards!
inside this : http://developer.android.com/guide/components/services.html , Extending the Service class will help you !
Related
I want to develop Text-To-Speech (TTS) feature in my app. It must be implemented inside Service, because user may leave "details" Activity and get back to "main" Activity or even leave my app, and it should still speak out loud text. Since Oreo introduced some background limitations for services and I must support 4.0+ I have to use JobIntentService
Problem is that TTS have async implementation and JobIntentService gets killed just after onHandleWork finishes its job, even when I use startForeground (in my code showSpeakingNotification)
Funny part is that when I but a breakpoint inside onHandleWork after 'speakOut' method or just uncomment Thread.sleep service is working and reading my text (and foreground notification is present).
Question is how to prevent "auto-killing" my service when it is actually running, but using asynchronous feature inside?
#Override
protected void onHandleWork(#NonNull Intent intent) {
if (ACTION_SPEAK.equals(intent.getAction()) && intent.hasExtra(EXTRA_TEXT_ARRAY)) {
ArrayList<String> textArr = intent.getStringArrayListExtra(EXTRA_TEXT_ARRAY);
showSpeakingNotification(textArr.get(0));
if (ttsInitialized)
speakOut(textArr);
else if (ttsInitListener != null)
ttsInitListener.setPendingText(textArr);
} else if (ACTION_STOP_SPEAKING.equals(intent.getAction())) {
if (ttsInitialized && tts.isSpeaking())
tts.stop();
}
try {
//Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
just uncomment Thread.sleep service is working and reading my text
When you add Thread.sleep(10000); it blocks the current thread as a result, it doesn't respond to your speech. When you comment it current thread is free to read your data
Question is how to prevent "auto-killing" my service when it is
actually running, but using asynchronous feature inside?
Note possible. Your requirements can be fulfilled using Foreground Service. Refer to this SO for implementing the Foreground Service
Is there a way to implement timeout feature in the following scenarios?
A web application with html pages and native screens.
1.When the application is in the background for 5 min -> destroy the application.
2.When the application is in the foreground but not receiving any user interaction for 5 min ->destroy the application.
I think you can use this.
ApplicationConstants.TIMEOUT_IN_MS will be 300000 //5 min
private void timeout() {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
System.exit(0);//close aplication
}
}, ApplicationConstants.TIMEOUT_IN_MS);
}
#Override
protected void onPause() {
super.onPause();
timeout();
}
Cheers,
Regarding background state:
There is no need to kill the app's process manually by default. The Android OS does this by itself if there is a need to free up resources for the other applications.
See this guide for a reference.
Though if you need to perform some background work during this "idle time", you may start a Service to perform those operations and then stop it from code.
Regarding foreground state:
I think the best approach to use here is to send Messages to a Handler of the Main thread of your application, since you do not know if the user will interact with the UI again after they leave. When the user comes back to the UI, you may clear the message queue, using Handler's removeMessages method.
I do not recommend you to finish the process with System.exit(0) in Android.
I'm writing an app that plays an audio file and I want it to continue doing so while minimized. I've done this, but I want the audio playback to be on a separate thread, because according to the Android developer website, CPU-heavy services work better on a separate thread.
First I tried using IntentService (this was the perfect solution). However, for some stupid reason, the service destroys itself once the code executed - which is immediately after it starts playing the file. I couldn't prevent this.
Then I created a Thread that runs the Service. However, I don't know how to make the Thread stop the service when needed - the best thing I could do is this:
serviceThread = new Thread() {
public void run() {
while (true) {
if (playAudio) {
startService(new Intent(getApplicationContext(),
MusicService.class));
playAudio = false;
}
if (stopAudio) {
stopService(new Intent(getApplicationContext(),
MusicService.class));
stopAudio = false;
}
}
}
};
Evidently, after that I set startService to true to start the service and I set stopService to true to stop it. However, I believe the Thread has to keep doing the check all the time, thus doing a lot of useless work all the time. I'm not even sure why is the app working, isn't it doing like million checks every second?
How can I properly do this?
Assuming you can't block the thread that the service runs in, you can add a java.lang.Thread.Sleep at the end of the loop if you're worried about doing too much work.
You might also want to read up thread scheduling and time slicing to understand why your app is still working (but probably using a lot more CPU than necessary).
Having read most of the available documentation on Android services on the developer site and here in stackoverflow, I'm still confused by several aspects of running a service in a separate task. Hopefully someone can put me on the right track.
Let's say we have trival service framework such as
public class HliService extends Service {
#Override
public void onCreate() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// If we get killed, after returning from here, restart
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// We don't provide binding, so return null
return null;
}
#Override
public void onDestroy() {
}
}
and in the manifest, I have
<service android:name=".HliService" android:process=":HLI_Comms"/>
so that the service runs in its own thread.
The intent of the service is to provide a background task that will communicate
to a device using a TCP socket and do some other stuff. At the risk of ignoring battery issues etc, basically I'd like it to run forever.
Something like
// Method that communicates using a TCP socket, and needs to send
// information back to the activity and receive messages from activity
// not shown here.
private void dummytask() {
boolean keepGoing = true;
while (keepGoing) {
// do useful stuff in here
// sets keepGoing false at some point
}
stopSelf();
}
What is the best way to initiate this method/task ?
I have looked at code in the developer site that uses a message handler and a looper, which I only partly understand, but it seems very complicated and perhaps more than I require?
I don't believe I can call this method from either onCreate() or onStartCommand() since then neither would complete when invoked from the system ? Should I start it with a timer or alarm?
I will need to add a message handler to communicate with the the gui activity, but since I'm starting the service in another thread (by virtue of the manifest "process" instruction), do I need to use AIDL instead?
I have also looked at using AysnchTask rather than extending Service, but it seems better suited to running a task and then terminating.
so that the service run in its own thread.
That puts the service in its own process. This is generally something to be avoided, as it consumes extra RAM and CPU (for IPC). You can create a thread just by creating a Thread or any number of other means, most of which have been in Java for a decade or so.
At the risk of ignoring battery issues etc, basically I'd like it to run forever.
It is pretty much impossible for a service to run forever. Users or the OS will get rid of your service eventually.
What is the best way to initiate this method/task ?
Call dummytask() from a background thread.
do I need to use AIDL instead?
No. Your service can broadcast an Intent, or invoke a PendingIntent supplied by the activity, or send a Message via a Messenger supplied by the activity, etc. The best would be to use the LocalBroadcastManager from the Android Support package, but that will not work across process boundaries, forcing you into more expensive communications options.
I think you could use a IntentService which you run by setting up a (regular) alarm (AlarmManager.setRepeating) with a PendingIntent in it. You can notify the UI by broadcasting an Intent from the IntentService and receiving it in your UI through a BroadcastReceiver.
I am implementing a Service that starts when Android boots, and it's supposed to scan every 10 mins for nearby Bluetooth devices. When it discovers devices, it does some work. Also, this periodic scanning should occur the entire time the device is on. I am trying to schedule a TimerTask, but I don't understand how to use it. I guess it should start this service and let the service do the work instead of writing the code in the TimerTask's run method? How would I start the service from the TimerTask as this seems the easiest way to remedy my problem, but TimerTask is part of java.util and not one of Android's classes.
I just found Android's AlarmManager. Should I use that? Can it start a Service?
So far I have this, but I need help:
class Timer extends Service
{
private Handler myHander;
Runnable r = new Runnable()
{
run()
{
startService(new Intent(Timer.this.getApplicationContext() ,MyService.class));
myHandler.postDelayed(r,10 minutes);
}
}
onCreate()
{
myHandler=new MyHandler();
}
onStartCommand()
{
//Do the bluetooth work.
r.run();
}
onDestroy()
{
super.onDestroy();
myHandler.removeCallback(r);
}
}
class MyService extends Service
{
}
Sorry, I don't understand how the formatting works here.
Will I need to override onDestroy() in the Service? Where to do I use stopService() ?
You need to:
Write service that will be started from one of your activities and/or after device has booted.
In your service in onStart/onStartCommand you need to schedule either using Handler or AlaramManager periodic updates.
The difference between Handler and AlarmManager in this case will be that: Handler will not run when device is in deep sleep, while you can configure AlaramManager to wake up the device and run your code.
I'd recommend to go with Handler, as its easier and because you said you only need to run your code when device is awake.
And one more thing, Handler doesn't use extra thread while TimerTask does. And this is considered a bad practice on Android to waste on thread for timer only.
An example code for how to repeat task using Handler can be found here: Repeat a task with a time delay?.