My IntentService looks like this:
public class MusicService extends IntentService{
final static String NAME = "MusicService";
//------------------------------------------------------------------------------
public MusicService(String name) {
super(NAME);
}
//------------------------------------------------------------------------------
public MusicService() {
super(NAME);
}
//------------------------------------------------------------------------------
#Override
protected void onHandleIntent(Intent intent) {
// Toast never comes up
Toast.makeText(getApplicationContext(), NAME, Toast.LENGTH_SHORT).show();
PodcastrApplication.newInstance().getMediaPlayer().start();
}
//------------------------------------------------------------------------------
}
I have a MediaPlayer that I keep in my Application to reduce object instantiations. The idea is that once the app goes out of focus, the media player will play. However, the service is never fired.
Here is how I am calling the service from the onStop() of my Fragment
showMediaPlayerNotification();
Intent music = new Intent(getActivity(), MusicService.class);
getActivity().startService(music);
I have it declared in the manifest also. There is no error in logcat, either.
What is going on?
Update 1:
Once you call startService(), the IntentService does the work defined
in its onHandleIntent() method, and then stops itself.
Is it that the service is stopping itself because it is just one line of execution?
Should I move the media player to a thread?
Update 2:
<service
android:name=".service.MusicService"
android:enabled="true"
android:exported="false" />
You've called Toast.makeText() in a background thread!, Any UI stuff must be done in UI thread.
Note that: IntentService uses a background thread but Service uses UI thread
You can try:
public class MusicService extends IntentService{
Handler mHandler;
final static String NAME = "MusicService";
//------------------------------------------------------------------------------
public MusicService(String name) {
super(NAME);
mHandler = new Handler();
}
//------------------------------------------------------------------------------
public MusicService() {
super(NAME);
mHandler = new Handler();
}
//------------------------------------------------------------------------------
#Override
protected void onHandleIntent(Intent intent) {
mHandler.post(new Runnable{
#Override
public void run(){
Toast.makeText(getApplicationContext(), NAME, Toast.LENGTH_SHORT).show();
}
});
// Toast never comes up
PodcastrApplication.newInstance().getMediaPlayer().start();
}
//------------------------------------------------------------------------------
}
Related
I am building a toast every 5 sec using some sample found.
The code works ok, but the service wont stop even i stopped the app.
Can anyone point out what is wrong?
public class MyService extends Service {
public static final long INTERVAL=5000;//variable to execute services every 5 second
private Handler mHandler=new Handler(); // run on another Thread to avoid crash
private Timer mTimer=null; // timer handling
#Nullable
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("unsupported Operation");
}
#Override
public void onCreate() {
// cancel if service is already existed
if(mTimer!=null)
mTimer.cancel();
else
mTimer=new Timer(); // recreate new timer
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(),0,INTERVAL);// schedule task
}
#Override
public void onDestroy() {
Toast.makeText(this, "In Destroy", Toast.LENGTH_SHORT).show();//display toast when method called
mTimer.cancel();//cancel the timer
}
//inner class of TimeDisplayTimerTask
private class TimeDisplayTimerTask extends TimerTask {
#Override
public void run() {
// run on another thread
mHandler.post(new Runnable() {
#Override
public void run() {
// display toast at every 5second
Toast.makeText(getApplicationContext(), "Notify", Toast.LENGTH_SHORT).show();
}
});
}
}
}
I keep receiving the toast Notify even the app had been closed.
add onTaskRemoved() method in your MyService,like this
#Override
public void onTaskRemoved(Intent rootIntent) {
stopSelf();///its will stop service
super.onTaskRemoved(rootIntent);
}
In your Activity onStop() you should call stopService(new Intent(context,YourService.class)); in order to stop your service
I have a service which I start from my Activity.
Now the serivce performs some task by starting a new thread from onStartCommand()
I want to stop the service after the thread has finished its job.
I tried using a Handler like this
public class MainService extends Service{
private Timer myTimer;
private MyHandler mHandler;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mHandler = new MyHandler();
myTimer = new Timer();
myTimer.schedule(new MyTask(), 120000);
return 0;
}
private class MyTask extends TimerTask{
#Override
public void run() {
Intent intent = new Intent(MainService.this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
mHandler.sendEmptyMessage(0);
}
}
private static class MyHandler extends Handler{
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.e("", "INSIDE handleMEssage");
//stopSelf();
}
}
First it was giving me a warning that if handler class is not static it will cause leaks
After I made it static, stopSelf() can not be called, because its non static.
Is my approach correct or is there a simpler way around ?
you should use IntentService rather service. It starts automatically in separate thread and stop itself as task completes.
public class MyService extends IntentService {
public MyService(String name) {
super("");
}
#Override
protected void onHandleIntent(Intent arg0) {
// write your task here no need to create separate thread. And no need to stop.
}
}
Use IntentService its base class for Services that handle asynchronous requests (expressed as Intents) on demand. 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.
try this,
private static class MyHandler extends Handler{
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.e("", "INSIDE handleMEssage");
MainService.this.stopSelf();;
}
}
In first Activity I've started this service:
public class TaskMsg extends Service
{
private static Timer timer;
private Context ctx;
public IBinder onBind(Intent arg0)
{
return null;
}
public void onCreate()
{
super.onCreate();
timer = new Timer();
ctx = this;
startService();
}
private void startService()
{
timer.scheduleAtFixedRate(new mainTask(), 0, 35000);
}
private class mainTask extends TimerTask
{
public void run()
{
toastHandler.sendEmptyMessage(0);
}
}
public void onDestroy()
{
timer.cancel();
super.onDestroy();
}
private final Handler toastHandler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
// for example, 2*3;
}
}
}
In handleMessage method where I have a few operation. It's working fine.
But I have problem, because I would like to call to activity (from this Service) that in service has new result operation. In all Activity in my project, I have method Update. I need only information that Handler in Service returned new information to all Activity or current Activity.
May be you can use a custom broadcast receiver. From the service you can broadcast the message and can write a receiver in your activity. In onReceive() in your activity, you can call to your update() method.
Hope you understand what I mean
Thank You! Is it good solution for few activities?
Intent intent = new Intent(Activity1.UPDATE);
sendBroadcast(intent);
intent = new Intent(Activity2.UPDATE);
sendBroadcast(intent);
intent = new Intent(Activity3.UPDATE);
sendBroadcast(intent);
In my application, there is a service class. I want to start an intent 10 seconds later with this service. When I try a basic toast message instead of starting intent, it works. However, when I write startActivity(intent) an error occurs. Here is my code. Where am I making mistake?
public class EkraniKilitle extends Service {
Handler yardimci;
Intent kilitEkrani;
final static long ZAMAN = 10000;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
kilitEkrani = new Intent(EkraniKilitle.this, KilitEkrani.class);
yardimci = new Handler();
yardimci.postDelayed(new Runnable() {
#Override
public void run() {
servisiDurdur();
startActivity(kilitEkrani);
}
}, ZAMAN);
}
public void servisiDurdur() {
stopService(new Intent(this, EkraniKilitle.class));
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
i guess you need to add your second activity to the manifest
after </activity> add <activity android:name=".MySecondClass"/>
Call startActivity(kilitEkrani); before servisiDurdur(); and to stop your current service all what you need is to call stopSelf() you do not have to use stopService
I am continuing to study from the book "Pro Android 2," working through the Service example that consists of two classes: BackgroundService.java and MainActivity.java. The MainActivity class is shown below and has a couple buttons. The unbind button, unbindBtn, stops the Service but doesn't appear to do much else like kill the thread the Service started.
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.d(TAG, "starting service");
Button bindBtn = (Button)findViewById(R.id.bindBtn);
bindBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
Intent backgroundService = new Intent(MainActivity.this, com.marie.mainactivity.BackgroundService.class);
startService(backgroundService);
}
});
Button unbindBtn = (Button)findViewById(R.id.unbindBtn);
unbindBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
stopService(new Intent(MainActivity.this, BackgroundService.class));
}
});
}
}
The documentation says "if your service is going to do any CPU intensive work or blocking operations..., you should create a new thread within the service to do that work." And that's exactly what the BackgroundService class does below. As you can see below I've added a while(true) loop in the thread's run() method to see what happens to the thread when I stop the Service.
public class BackgroundService extends Service {
private NotificationManager notificationMgr;
#Override
public void onCreate() {
super.onCreate();
notificationMgr = NotificationManager)getSystemService(NOTIFICATION_SERVICE);
displayNotificationMessage("starting Background Service");
Thread thr = new Thread(null, new ServiceWorker(), "BackgroundService");
thr.start();
}
class ServiceWorker implements Runnable
{
public void run() {
// do background processing here...
long count = 0;
while (true) {
if (count++ > 1000000)
{
count = 0;
Log.d("ServiceWorker", "count reached");
}
}
//stop the service when done...
//BackgroundService.this.stopSelf();
}
}
#Override
public void onDestroy()
{
displayNotificationMessage("stopping Background Service");
super.onDestroy();
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
private void displayNotificationMessage(String message)
{
Notification notification = new Notification(R.drawable.note, message, System.currentTimeMillis());
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0);
notification.setLatestEventInfo(this, "Background Service", message, contentIntent);
notificationMgr.notify(R.id.app_notification_id, notification);
}
}
When I press the unbind button, unbindBtn, in the MainActivity class I trust the Service in this example will be stopped. But from what I can see in logcat the thread that was started by the Service continues to run. It's like the thread is now some kind of orphan with no apparent way to stop it. I've seen other source code use a while(true) loop in a thread's run() method. This seems bad unless a way to break out of the loop is provided. Is that typically how it's done? Or are there other ways to kill a thread after the Service that started it has stopped?
You should provide a 'running' boolean.
while(running) {
//do your stuff
}
You want to make it something that you can update. Perhaps your Service's onDestroy() method should call a stopProcessing() method on your Runnable, which will set the 'running' boolean to false.