如何在 Android 中服务 onDestroy 后保持对象变量处于活动状态?
Posted
技术标签:
【中文标题】如何在 Android 中服务 onDestroy 后保持对象变量处于活动状态?【英文标题】:How to keep object variable alive after service onDestroy in Android? 【发布时间】:2017-03-18 04:37:20 【问题描述】:我的IntentService
班级中有一个MediaRecorder
。
我想要
-
运行
IntentService
开始录制音频
运行IntentService
以停止录制音频
我使用IntentService
是因为我希望即使我的手机屏幕关闭也能运行录音。服务在后台运行,所以这是一个好方法,对吧?
无论如何,我在第 1 步在我的IntentService
中启动我的MediaRecorder
。
在第 2 步,我实例化的 MediaRecorder
为 NULL。看来IntentService
里面的所有变量值都被重置了,因为服务结束并调用onDestroy
。
我该怎么办?如何保留对我的 MediaRecorder
的引用?
更新:粘贴我的 IntentService
类
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");
【问题讨论】:
在此处粘贴 IntentService 类 完成@ZeeshanShabbir 【参考方案1】:通过使用服务而不是意图服务来修复它。
这篇文章很有帮助。 Service.onDestroy() is called directly after creation, anyway the Service does its work
基本上,IntentService 的设计目的是在 onHandleIntent 中的代码完成后立即停止所有服务。因此,我永远无法让我的 MediaRecorder 保持活力。
使用普通服务,我可以更好地控制服务的生命周期。我可以在需要时启动和停止它。使用 IntentService,这是不可能的。
【讨论】:
以上是关于如何在 Android 中服务 onDestroy 后保持对象变量处于活动状态?的主要内容,如果未能解决你的问题,请参考以下文章
如何防止 onPause() 之后调用 onDestroy()?
Android:在活动中 onStart()、onStop()、onDestroy() 的开头或结尾调用 super()?