Android 服务在后台运行?
我正在构建的应用程序的一个功能具有记录功能。我通过在服务中启动MediaRecorder对象来实现这一点:Android 服务在后台运行?,android,service,background,Android,Service,Background,我正在构建的应用程序的一个功能具有记录功能。我通过在服务中启动MediaRecorder对象来实现这一点: Intent intent = new Intent(v.getContext(), RecordService.class); Messenger messenger = new Messenger(handler); intent.putExtra("COUNT", basic); intent.putExtra("MESSENGER", messenger); v.getConte
Intent intent = new Intent(v.getContext(), RecordService.class);
Messenger messenger = new Messenger(handler);
intent.putExtra("COUNT", basic);
intent.putExtra("MESSENGER", messenger);
v.getContext().startService(intent);
//service
//...
mRecorder = new MediaRecorder();
//...
现在我引入了一个通知,它必须让用户知道录制本身的状态,因为如果你回家或点击backbutton,它必须保持录制。因此,如果点击通知,您将返回应用程序
这就是我正在努力的地方,如果我单击通知,我会返回应用程序,但所有内容都设置为初始状态(计时器返回00:00:00,我可以再次点击录制按钮而不是暂停按钮)我应该完成的当然是它保持记录,并且我可以看到正在进行的计时器+停止按钮。注意:计时器现在不是服务。。你知道我该怎么处理吗 编辑 假设我关闭了应用程序,服务仍在运行。重新打开应用程序(以及最初调用服务的活动)我们可以使用:
private boolean isMyServiceRunning() {
ActivityManager manager = (ActivityManager) myContext.getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (MyService.class.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
因此,我已经部分介绍了这一点,但是,从该服务传递到该活动的变量现在已经不存在了。似乎我的活动中的处理程序在重新打开该活动后没有拾取它们
private Handler handler = new Handler() {
public void handleMessage(Message message) {
//..
Bundle bundle = message.getData();
fileName = bundle.getString("FILENAME");
tvFileName.setText(fileName);
Log.e("Filename", "transfered: " + fileName);
};
};
//编辑
片段:
public class LayoutOne extends Fragment implements OnClickListener {
//vars
@Override
public void onPause() {
super.onPause();
if (mRecorder != null) {
mRecorder.release();
mRecorder = null;
}
if (mPlayer != null) {
mPlayer.release();
mPlayer = null;
}
}
private Handler handler = new Handler() {
public void handleMessage(Message message) {
int i = message.arg1;
Bundle bundle = message.getData();
fileName = bundle.getString("FILENAME");
tvFileName.setText(fileName);
Log.e("Handler", "Succesfully transfered: " + (Integer.toString(i)));
Log.e("Filename", "Succesfully transfered: " + fileName);
};
};
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bRecord:
if (mStartRecording) {
mStartRecording = false;
Intent intent = new Intent(v.getContext(), RecordService.class);
Messenger messenger = new Messenger(handler);
intent.putExtra("MESSENGER", messenger);
v.getContext().startService(intent);
} else {
mRecordButton.setText("Record");
Intent stopIntent = new Intent(v.getContext(),
RecordService.class);
try {
v.getContext().stopService(stopIntent);
} catch (Exception e) {
e.printStackTrace();
}
mStartRecording = true;
}
break;
case R.id.bStop:
Intent stopIntent = new Intent(v.getContext(), RecordService.class);
v.getContext().stopService(stopIntent);
break;
}
}
public static Fragment newInstance(Context context) {
LayoutOne f = new LayoutOne();
return f;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
root = (ViewGroup) inflater.inflate(R.layout.layout_one, null);
myContext = container.getContext();
//buttons
mgr = (NotificationManager) myContext.getSystemService(Context.NOTIFICATION_SERVICE);
return root;
}
public void notifyMe(View v) {
Notification note = new Notification(R.drawable.ic_launcher,
getString(R.string.notificationbar), System.currentTimeMillis());
PendingIntent i = PendingIntent.getActivity(myContext, 0, new Intent(
myContext, ViewPagerStyle1Activity.class), 0);
note.setLatestEventInfo(myContext, getString(R.string.app_name),
getString(R.string.notification), i);
note.number = ++count;
note.vibrate = new long[] { 500L, 200L, 200L, 500L };
note.flags |= Notification.FLAG_AUTO_CANCEL;
mgr.notify(NOTIFY_ME_ID, note);
}
public void clearNotification(View v) {
mgr.cancel(NOTIFY_ME_ID);
}
// /SHARED PREFERENCES SETTINGS///
//…
private void initiatePopupWindow() {
//..
}
@Override
public void onResume() {
super.onResume();
Intent intent = new Intent(myContext, RecordService.class);
myContext.startService(intent);
myContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
LocalBinder binder = (LocalBinder) service;
myService = binder.getService();
//myService.setBound(true);
initializeUI();
}
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
};
protected void initializeUI() {
//..
}
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
myContext.unbindService(mServiceConnection);
}
@Override
public void onStop() {
// TODO Auto-generated method stub
myContext.unbindService(mServiceConnection);
}
}
//服务
public class RecordService extends Service {
//vars
public class LocalBinder extends Binder {
RecordService getService() {
return RecordService.this;
}
}
@Override
public void onCreate() {
Log.i("Oncreate", "Service onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Bundle extras = intent.getExtras();
if (extras != null) {
messenger = (Messenger) extras.get("MESSENGER");
count = Integer.toString(extras.getInt("COUNT"));
try {
Message message = new Message();
int arg = 0;
message.arg1 = arg;
mFileNamePass=”test”;
Bundle bundle = new Bundle();
bundle.putString("FILENAME", mFileNamePass);
message.setData(bundle);
messenger.send(message);
} catch (android.os.RemoteException e1) {
Log.w(getClass().getName(), "Exception sending message", e1);
}
}
else {
Log.i("Extras","Didn't find extras");
}
Runnable r = new Runnable() {
@Override
public void run() {
checkIfFolderExists();
String dateFull = calculateDate();
mFileName = Environment.getExternalStorageDirectory()
.getAbsolutePath();
mFileName += "test.3gp";
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setOutputFile(mFileName);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
mRecorder.prepare();
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() failed");
}
mRecorder.start();
Log.i("Service", "Service running");
}
};
Thread t = new Thread(r);
t.start();
return RecordService.START_STICKY;
}
@Override
public void onDestroy() {
Runnable stopRecord = new Runnable() {
@Override
public void run() {
mRecorder.stop();
mRecorder.release();
mRecorder = null;
}
};
Thread stopRecordThread = new Thread(stopRecord);
stopRecordThread.start();
Log.i("Service", "Service stopped");
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
首先,您不需要检查您的
服务是否由某个ActivityManager
方法运行。如果在onResume()
中调用startService()&&bindService()
,Android足够聪明,只要绑定到服务即可,如果它已经运行,如果没有,它将创建服务
,并经过适当的文档化生命周期,然后绑定到它
在这里,您可以做的是:
@Override
public void onResume() {
super.onResume();
Intent intent = new Intent(this, YourService.class);
startService(intent);
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
现在,让我们假设您的服务已经在运行,您希望获得它的正确值。在ServiceConnection()
的onServiceConnected()
方法中,当绑定完成时,可以调用类似initializeUI()的方法:
private ServiceConnection mServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
LocalBinder binder = (LocalBinder) service;
myService = binder.getService();
myService.setBound(true);
initializeUI();
}
public void onServiceDisconnected(ComponentName className) {
}
};
现在,您有了myService
变量,该变量指向您的Service
对象,您可以调用getters
,比如myService.getTimer()
和myService.isRecording()
顺便说一句,我不知道当你退出应用程序时,你是否也在努力保持服务运行
如果您这样做,只要Android有足够的内存,使用startService(intent)
将保持服务的运行。您必须有一段代码,可以在其中调用myService.stopService()
,否则,该服务将运行很长时间。更新了我的问题,得到了解决方案,但从该服务传递的变量是否在重新打开活动后未被拾取..“一切都设置为初始状态”,您的onPause和onResume中有什么?我正在启动一个片段,命令来自于该活动,在该片段中我只有一个onPause:@Override public void onPause(){super.onPause();if(mRecorder!=null){mRecorder.release();mRecorder=null;}当用户从您的组件返回主页时,onPause将被调用,因此我认为在onPause中释放录音机是不合适的。谢谢@tolgap!我将在今晚深入了解它,并会回复您!您好@tolgap,我试图用您的建议修复我的错误(我用我的建议编辑了我的问题)但是我一直得到错误:IllegalStateException位于(RecordService.java:106)只要我想开始录制。我不知道我的代码的总体结构是否正确,你可能会有主意?谢谢!@MatthiasVanb服务的全部要点是它在后台进程上运行。你不需要为所有事情启动新的Runnable。其次,你可以在应用程序运行后立即启动服务,并使用getter和服务的设置者,从你的片段开始记录并获取他们的数据OK@tolgap,我会重新编码它,它实际上是完全有意义的:)。你知道是什么导致了这个错误吗?因为在我使用mServiceConnection之前,我从未见过这个错误。。一旦你在onResume()中启动服务
,您不能通过再次创建它来重新启动它。您只需将录制逻辑移动到服务中名为startRecording()
的方法,然后在onclick中调用服务。startRecording()
。因此,除了返回RecordService.START\u STICKY;
,您的onStart命令
方法应该是空的,所有其他代码都应该移动到它自己的方法中,您将从片段
调用该方法。
public void initializeUI() {
timerTextview.setText( myService.getTime() );
someOtherUiElement.setText( myService.getSomething() );
if( myService.isRecording() )
recordButton.setImageResource( R.drawable.pause );
} //etc...