Xemega
Xemega

Reputation: 31

service keep crashing on OnDestroy()

I'm creating a service that runs a mediaplayer for a set period of time.This service gets a constant value that I defined in another class and based on that the duration of the playing is determined.

I looked all over the web but couldn't find a solution or a similar problem , spent hours trying to no avail

  package com.quantyam.sleepbaby.sleepbaby;

 import android.app.IntentService;
import android.app.Service;
import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.widget.Toast;

 public class ContinousService extends IntentService {

private static final String TAG = "HelloService";
MediaPlayer player;
private boolean isRunning = false;
int time = 0;
Thread runner;
boolean keepplaying=true;

Handler mHandler = new Handler();

boolean keepgoiong = true;

public ContinousService() {
    super("ContinousPlayer");
}


private void sendMessageToActivity(int msg) {
    Intent intent = new Intent("intentKey");

    intent.putExtra("current_timing", msg);
    LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}


@Override
public void onCreate() {
    Log.i(TAG, "Service onCreate");

    isRunning = true;
}

public static String
        ACTION_CONTINOUS_PLAY = "";


@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    System.out.println("******************************************* selected DUration  = " + Constant.PlayDuration);
    Log.i(TAG, "Service onStartCommand");

    //Creating new thread for my service
    //Always write your long running tasks in a separate thread, to avoid ANR
    new Thread(new Runnable() {

        @Override
        public void run() {
            runner = Thread.currentThread();

            //Your logic that service will perform will be placed here
            //In this example we are just looping and waits for 1000 milliseconds in each loop.
            while (keepgoiong) {
                try {
                    Thread.sleep(1000);

                    startplaying();
                    time++;
                } catch (Exception e) {
                    e.printStackTrace();
                }

                if (isRunning) {
                    Log.i(TAG, "Service running and time is = " + time);
                }
            }

            //Stop service once it finishes its task
            stopSelf();
        }
    }).start();

    return Service.START_STICKY;
}


public void startplaying() {

    try {

        if(keepplaying) {
            if (player == null) {
                AssetFileDescriptor afd = getAssets().openFd("music/" + Constant.SelectedMusic);
                player = new MediaPlayer();
                player.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
                player.prepare();
                player.start();
                System.out.println("============================= player Started!");
            }


            final int duration = Integer.parseInt(Constant.PlayDuration) * 15;
            int timeleft = duration - time;
            sendMessageToActivity(timeleft);
            System.out.println("============================= time left = " + timeleft);
            if (player.isPlaying() && timeleft > 0) {


            } else if (!player.isPlaying() && timeleft > 0) {
                System.out.println("================================== Run Again!");

                //    player.prepare();
                player.start();
            } else if (player.isPlaying() && timeleft <= 0) {

                System.out.println("============================= Time is up!");
                player.stop();
                keepplaying=false;
                keepgoiong = false;

            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}


@Override
public IBinder onBind(Intent arg0) {
    Log.i(TAG, "Service onBind");

    return null;
}

@Override
protected void onHandleIntent(@Nullable Intent intent) {

}

Handler handler = new Handler();

@Override
public void onDestroy() {
    keepgoiong = false;
    isRunning=false;
    keepplaying=false;
    player.stop();
 super.onDestroy();
 //   stopSelf();

    Log.i(TAG, "Service onDestroy");
}

}

when the time is up I call stopSelf() but everytime I get the following error message :

E/AndroidRuntime: FATAL EXCEPTION: main
              Process: com.quantyam.sleepbaby.sleepbaby, PID: 6550
              java.lang.RuntimeException: Unable to stop service com.quantyam.sleepbaby.sleepbaby.ContinousService@cbde8b0: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.os.Looper.quit()' on a null object reference
                  at android.app.ActivityThread.handleStopService(ActivityThread.java:3732)
                  at android.app.ActivityThread.-wrap30(ActivityThread.java)
                  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1745)
                  at android.os.Handler.dispatchMessage(Handler.java:102)
                  at android.os.Looper.loop(Looper.java:154)
                  at android.app.ActivityThread.main(ActivityThread.java:6692)
                  at java.lang.reflect.Method.invoke(Native Method)
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468)
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358)
               Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.os.Looper.quit()' on a null object reference
                  at android.app.IntentService.onDestroy(IntentService.java:138)
                  at com.quantyam.sleepbaby.sleepbaby.ContinousService.onDestroy(ContinousService.java:153)
                  at android.app.ActivityThread.handleStopService(ActivityThread.java:3715)
                  at android.app.ActivityThread.-wrap30(ActivityThread.java) 
                  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1745) 
                  at android.os.Handler.dispatchMessage(Handler.java:102) 
                  at android.os.Looper.loop(Looper.java:154) 
                  at android.app.ActivityThread.main(ActivityThread.java:6692) 
                  at java.lang.reflect.Method.invoke(Native Method) 
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468) 
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358) 

my code https://codeshare.io/5MJEVQ

Upvotes: 1

Views: 717

Answers (1)

doubleA
doubleA

Reputation: 2456

An IntentService runs on its own thread. So what you are doing is starting a thread that starts another thread that starts the media player and waits before calling stopSelf() on the first thread. An intent service is only available for as long as it has work. If the intent service launches another thread... its work is done and it will go away.

When you call the stopSelf() method your Intent service has already gone away because it started the thread and has completed its work...

I would first suggest that when the intent service starts you start the media player. Then use a PostDelayed runnable to stop the media player when it is finished. Something like below. Note: that this will still not work as is because the IntentService will finish its work once it starts the postDelayed Runnable. Solution is to use a Service instead of an IntentService.

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    System.out.println("******************************************* selected DUration  = " + Constant.PlayDuration);
    Log.i(TAG, "Service onStartCommand");
    startMediaPlayer();
    new Handler().postDelayed(new Runnable() {
    public void run () {
        stopSelf();
        }
    }, playDuration);
    return Service.START_STICKY;
}

I would suggest that you use a Service instead of an IntentService.

Here is an example of a media player in a service. It uses state and intents to receive actions from UI and Uses Broadcast receivers to update ui when needed.

Upvotes: 0

Related Questions