简体   繁体   中英

How to keep object variable alive after service onDestroy in Android?

I have a MediaRecorder in my IntentService class.

I want to

  1. Run an IntentService to start recording audio
  2. Run an IntentService to stop recording audio

I use IntentService because I want the audio recording to run even when my phone screen is turned off. Service runs in the background, so this is a good approach, right?

Anyways, I initiate my MediaRecorder in my IntentService at Step #1. At Step#2, my instantiated MediaRecorder is NULL. It seems that all variable values inside the IntentService are reset, because the service ends and calls onDestroy .

What should I do? How do I keep a reference to my MediaRecorder ?

Update: Pasting my IntentService class

package com.dan190.enregistreur.BackgroundService;

import android.app.IntentService;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.Log;

import com.dan190.enregistreur.RecordedFilesActivity;
import com.dan190.enregistreur.Util.RecordingStatus;

import java.io.IOException;
import java.util.Calendar;

/**
 * Created by Dan on 17/03/2017.
 */
public class RecorderService extends IntentService {
    private static final String TAG = RecorderService.class.getName();

    private MediaRecorder mMediaRecorder;

    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     *
     * @param name Used to name the worker thread, important only for debugging.
     */
    public RecorderService(String name) {
        super(name);
    }

    public RecorderService() {
        super("RecorderService");
    }
    /**
     * Handles intent.
     * Unwraps intent to find out if we need to start, pause, or stop
     * @param intent
     */
    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        Log.d(TAG, "onHandleIntent");

        Bundle bundle = intent.getExtras();
        int status = bundle.getInt(RecordingStatus.RECORDING_STATUS_KEY);
        switch (status) {
        case RecordingStatus.STANDBY:
            //do nothing
            break;
        case RecordingStatus.RECORDING:
            //if mediaPlayer is null, initiate
            //set datasource
            //prepare
            //record
            Log.d(TAG, "start recording");
            startRecording();
            break;
        case RecordingStatus.PAUSED:
            //pause
            Log.d(TAG, "pause recording");
            break;
        case RecordingStatus.STOPPED:
            //stop
            Log.d(TAG, "stop recording");
            stopRecording();
            Intent newIntent = new Intent(this, RecordedFilesActivity.class);
            startActivity(newIntent);
            break;
        case RecordingStatus.OPENDIR:
            //open recorded files
            Log.d(TAG, "open directory");
            getFileName();
            Intent newIntent2 = new Intent(this, RecordedFilesActivity.class);
            startActivity(newIntent2);
            break;
        default:
            break;
        }

    }

    /**
     * File stuff
     */
    private static String pathName,
    fileName;

    public static String getPath() {
        return pathName;
    }

    public static String getFilePath() {
        return fileName;
    }

    private String getFileName() {
        Calendar calendar = Calendar.getInstance();

        PackageManager m = getPackageManager();
        pathName = getPackageName();
        PackageInfo p = null;
        try {
            p = m.getPackageInfo(pathName, 0);
        } catch(PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        pathName = p.applicationInfo.dataDir;

        //        fileName = Environment.getExternalStorageDirectory() + "/" + Environment.DIRECTORY_DCIM + "/Recordings";
        fileName = pathName;
        fileName += String.format("/%d_%d_%d_%d_%d_%d.3gp", calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.HOUR_OF_DAY) + 1, calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND));

        return fileName;

    }

    /**
     * Recorder stuff
     */
    private void startRecording() {
        String fileName = getFileName();
        Log.d(TAG, String.format("file name is %s", fileName));

        if (mMediaRecorder == null) mMediaRecorder = new MediaRecorder();

        //NOTE that mediaRecorder cannot pause for API < 24, which is Android 7.0
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        mMediaRecorder.setOutputFile(getFileName());
        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

        try {
            mMediaRecorder.prepare();
        } catch(IOException e) {
            Log.e(TAG, "prepare() failed");
            e.printStackTrace();
        }

        try {
            mMediaRecorder.start();
        } catch(IllegalStateException e) {
            Log.e(TAG, e.getStackTrace().toString());
        }
    }

    private void stopRecording() {
        try {
            mMediaRecorder.stop();
            mMediaRecorder.reset();
        } catch(RuntimeException e) {
            e.printStackTrace();
        }
        releaseMediaRecorder();
    }

    private void releaseMediaRecorder() {
        if (mMediaRecorder != null) {
            mMediaRecorder.release();
            mMediaRecorder = null;
        } else {
            Log.w(TAG, "mediaRecroder is already Null");
        }

    }

    /**
     * Lifecycle stuff
     */
    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG, "onCreate");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "onDestroy");
    }

}

Fixed it by using Service instead of Intent service.

This post proved helpful. Service.onDestroy() is called directly after creation, anyway the Service does its work

Basically, IntentService is designed so that it will immediately stop all services after the code within onHandleIntent is finished. Thus, I was never able to keep my MediaRecorder alive.

With a normal Service, I am able to have more control over the lifecycle of my service. I can start and stop it when I want to. With IntentService, this is not possible.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM