I am trying to explore the world of Services in Android and I just wrote a small example where the activity has a button that triggers a notification.
The steps I do are:
Creating Intent intent = new Intent(context, MyService.class);
Inserting this in a PendingIntent and sending it to the NotificationManager
Then, once I click on the notification, the service (MyService) is started and launches a music soundtrack.
Using logging I saw that the click of the button and the actions of MyService both happen on the main thread, and I would like to know how can I make the service run in a separate background thread
p.s. MyService is extending Service and not IntentService because this last one terminates once executed
onStartCommand() is called on the main thread in your Service. If you want to launch a background Thread to do the work, you can just create your own Thread and start it inside onStartCommand(). Something like this:
Thread t = new Thread(new Runnable() {
public void run() {
// Put whatever code you want to run in background thread here
}
}).start();
Make sure that you have code that will shutdown running background threads if necessary when your Service needs to stop.
Have you ever work with RXjava?
1-get the librery:
Write these two lines in the build.gradle:
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.1.2'
2-Write these lines in onStartCommand:
io.reactivex.Observable.just(s).subscribeOn(AndroidSchedulers.mainThread())
.observeOn(Schedulers.io())
.subscribe(new io.reactivex.Observer<String>() {
#Override
public void onSubscribe(#NonNull Disposable d) {
}
#Override
public void onNext(#NonNull String s) {
//Write what you want here!! ;)
}
#Override
public void onError(#NonNull Throwable e) {
}
#Override
public void onComplete() {
}
});
and inside onNext write what ever you want, and it will execute on background thread
I hope it will be helpful
Related
public class DataManager extends IntentService {
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
}
public DataManager() {
super("DataManager");
setIntentRedelivery(true);
}
#Override
protected void onHandleIntent(final Intent intent) {
// download and parsing task done here
}
}
This is my intent service which i am using to download file and parse it. Now if i get a new request for a file download, i have to clear the ongoing task and start the download for new request cancelling the older one. so i use the below code for doing it :.
private void refreshSync() {
context.stopService(new Intent(context, DataManager.class));
final Intent mServiceIntent = new Intent(context, DataManager.class);
mServiceIntent.putExtras(bundle);
context.startService(mServiceIntent);
}
So the service gets killed and the next request to start service is intented. But the previous tasks starts again running two parallel tasks performing download. Basically the previous task doesnt get killed which i intended to.
Is there any work around to kill the ongoing task of the service and start another fresh task ?
Don't use IntentService. This doesn't match your requirements. IntentService is a simple Service that accepts a queue of work and processes the queue and then shuts itself down when the queue is empty.
You need more intelligence, and you are better off implementing that yourself. Just extend Service instead of IntentService. In onStartCommand() start a background Thread that downloads the data. Keep track of that background Thread in a member variable in the Service. If startService() gets called again, check if you already have a download in progress. If so, stop it and start a new background Thread to download the new file. To stop a background thread, you should provide a boolean variable in the Thread that gets examined every now and then inside the download loop. If that variable's state changes, it means the Thread should stop. This is a standard mechanism for stopping background threads in Java.
You are setting setIntentRedelivery(true);, that force the intents to survive calls of the service if they are not handled completely (if onHandleIntent doesn't manage to return). Taking into account the fact that IntentService has only one working thread (can execute only one task at a time) the behavior of the service completely depends on the onHandleIntent implementation. So you need either analyze implementation and change it according to you goals, or set setIntentRedelivery(false);
Refered to this library https://github.com/iammert/RadioPlayerService
I have this code for playing/pause radio
if (!mRadioManager.isPlaying())
mRadioManager.startRadio(RADIO_URL[0]);
else
mRadioManager.stopRadio();
and method for doing processes
#Override
public void onRadioStarted() {
runOnUiThread(new Runnable() {
#Override
public void run() {
//TODO Do UI works here.
mTextViewControl.setText("RADIO STATE : PLAYING...");
}
});
}
#Override
public void onRadioStopped() {
runOnUiThread(new Runnable() {
#Override
public void run() {
//TODO Do UI works here
mTextViewControl.setText("RADIO STATE : STOPPED.");
}
});
}
MyBroadcast Class
public class MyBroadcast extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent intent1 = new Intent(context, MainActivity.class);
intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent1);
}
But in android 7 when i turn the screen off after 5-8 min radio stops playing music. I have done another example by doing in background and it is still the same thing. Please can anyone suggest me how to build a radio app without being affected by doze
You have to create Foreground Service for that. Usually when any long process is running (like downloading, playing music or vieo etc.) it creates notification in status bar and lock screen.
Note: You should only use a foreground service for tasks the user expects the system to execute immediately or without interruption. Such cases include uploading a photo to social media, or playing music even while the music-player app is not in the foreground. You should not start a foreground service simply to prevent the system from determining that your app is idle.
https://developer.android.com/guide/components/services.html#Foreground
The link below is an extensive example. Keep in mind that this requires another permission level.
https://developer.android.com/training/scheduling/wakelock.html
What is the best way to implement an android Service (not IntentService) which polls a device using SNMP at regular intervals? I've tried implementing it with a Handler.postDelayed(Runnable) within onHandleIntent of IntentService. But later found it cannot be used in onHandleIntent() from this answer. My code just would not execute the runnable part.
make an IntentService not sleep until it executes a handler.postDelayed runnable
My code goes like:
public class MyPoller extends IntentService {
//Variable declarations
protected Handler handler;
public MyPoller() {
super("My service");
}
#Override
protected void onHandleIntent(Intent intent) {
.......
.......
runable = new Runnable() {
public void run() {
//My code here
handler.postDelayed(this, poll_interval);
}
};
handler.postDelayed(runable,poll_interval);
}
}
So I thought I could implement the same in a service, but I don't know how to implement this recurring task in a service also running it in a new thread. I found few answers demonstrating different ways of running recurring tasks in a new thread in a Service, but I'm confused.
Can someone suggest some way of implementing the same in a Service? It would be of great help. Thanks in advance.
My APP has to start some time consuming job when receiving ACTION_SCREEN_OFF, and interrupt the job when receiving ACTION_SCREEN_ON if job is still going on.
public class TimeConsumingWorkIntentService extends IntentService {
#Override
protected void onHandleIntent(Intent intent) {
TimeConsumingWork();
}
}
public class ScreenStatusReceiver extends BroadcastReceiver {
Intent intent = new Intent(mContext, TimeConsumingWorkIntentService.class);
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
mContext.startService(intent );
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
mContext.stopService(intent );
}
}
}
By print log of time, I find time consuming work is still going on stop the TimeConsumingWorkIntentService (when receiving ACTION_SCREEN_ON).
why ?
Use
// Cancel the runnable
myHandler.removeCallbacks(yourRunnable);
Ok , then you can do something like this
Runnable r = new Runnable{
public void run(){
if(booleanCancelMember != false){
// within this you make the call to handler and work
// Since you block the call the handler wont get repeated
}
}
}
You can't do this like that. When you start your IntentService, it will call onHandleIntent() on a separate worker thread. That mehod then calls TimeConsumingWork(). Stopping the service will not interrupt the execution of the worker thread. It just tells the worker thread that when it has finished processing the current Intent, it should stop.
What you will need to do is to have your TimeConsumingWork() method periodically look to see if it should stop. You can do this by setting a static boolean variable and have TimeConsumingWork() periodically check this variable and quit if it is set.
You don't need to call stopService() on an IntentService as it will stop itself when it has nothing to do.
Ok this got me really mad. Is there a restriction for services with countdowns?
I tried so many methods to make a countdown timer work in a service,but it always fails. It just never gets to the finish() part!
So is there a restriction with services and countdowns or what? Please help me...
Here is the service:
public class ss extends IntentService {
public ss() {
super("ss");
}
#Override
protected void onHandleIntent(Intent intent) {
new CountdownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
executemymethod(); //it never gets here!
}
}.start();
}
}
As you can see the code is simple and correct,but still the executemymethod(); never really executes! There are no errors... Please give me a solution!
If you want to do this kind of thing you should be using a regular Service and not an IntentService. Here's what the docs say about IntentService:
Clients send requests through startService(Intent) calls; the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.
Since the countdown is asynchronous, the work is complete after you start the countdown timer. The IntentService then finishes immediately, and probably shuts down the thread.