- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在构建的应用程序的其中一项功能具有记录功能。我通过在服务中启动一个 MediaRecorder 对象来做到这一点:
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();
//...
现在我引入了一个通知,它必须让用户知道录音本身的状态,因为如果你回家或点击后退按钮,它必须继续录音。因此,如果您点击通知,您将返回应用。
这就是我挣扎的地方,如果我点击通知,我会返回应用程序,但一切都设置为初始状态(计时器回到 00:00:00,我可以点击再次按下录制按钮而不是暂停按钮)我应该完成的当然是它继续录制并且我可以看到正在进行的计时器 + 停止按钮。注意:计时器现在不是服务。我应该如何处理这个问题有什么想法吗?
编辑
假设我关闭了应用程序,服务仍在运行。我们可以重新打开应用程序(以及最初调用服务的 Activity ):
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;
}
所以我已经部分涵盖了这一点,但是,从该服务传递到该 Activity 的变量现在消失了。似乎我的 Activity 中的处理程序在重新打开该 Activity 后没有拾取它们?
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);
};
};
//编辑
fragment :
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
方法检查您的Service
是否正在运行。如果您在 onResume()
中调用 startService() && bindService()
,Android 足够智能,只要绑定(bind)到 Service
就可以了运行,如果没有,它将创建 Service
并通过其正确记录的生命周期,然后绑定(bind)到它。
你可以在这里做的是:
@Override
public void onResume() {
super.onResume();
Intent intent = new Intent(this, YourService.class);
startService(intent);
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
现在,假设您的服务已经在运行并且您想要获得它的正确值。在 ServiceConnection()
的 onServiceConnected()
方法中,您可以在绑定(bind)完成时调用类似 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) {
}
};
现在,您有了指向您的 Service
对象的 myService
变量,您可以在该对象上调用 getters
,例如 myService.getTimer()
和 myService.isRecording()
。
public void initializeUI() {
timerTextview.setText( myService.getTime() );
someOtherUiElement.setText( myService.getSomething() );
if( myService.isRecording() )
recordButton.setImageResource( R.drawable.pause );
} //etc...
顺便说一句,我不知道您是否也在为在退出应用程序时保持服务运行而苦苦挣扎如果这样做,只要 Android 有足够的内存,使用 startService(intent)
将让您的 Service
保持运行。您必须有一段代码可以在其中调用myService.stopService()
,否则服务将运行很长时间。
关于android - 服务在后台运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15494917/
从 0 开始搭建一套后台管理系统,成本巨大,所以都会选择一套成熟的组件库,基于此,再堆叠业务逻辑。我们公司的组件库基于 Ant Design。Ant Design 包含一套完整的后台解决方案,不仅
在我的 IOS 应用程序中,我有一个标记为 retain 的 NSDate* 属性 当我的应用程序再次激活时,属性值已被释放。 我是否误解了属性和内存管理的工作原理,我该如何防范? 最佳答案 很明显,
我有一个使用 BackgroundWorker 组件的示例 WinForms 应用程序。它工作正常,但是当我点击 Cancel 按钮取消后台线程时,它并没有取消线程。当我点击 Cancel 按钮调用
我目前正在开发一个应用程序,该应用程序在启动时会对服务器执行 ping 操作,该服务器会为每个连接的设备返回一个唯一标识符。设备每 5 秒从服务器检索另一页以获取一组不同的数据。这个唯一的 ID 可以
我正在开发一个应用程序,当它通过主页按钮在后台按下时,计时器应该启动,当应用程序返回前台并且计时器已经过了一定时间时,应该是执行。 我的问题是 当我的应用程序转到背景/前景? 是否有特殊的方法或其他技
我有 map View ,其中几乎没有 MKPointAnnotation。 一切正常,但是, View 的 MKPoiintAnnotation 的“背景”是“不可见的”,因此不是很“可见”。 我想
我在 iOS 中开发广告数据应用程序。我的应用程序广告数据在前台很好。但我想在 ios 后台宣传信标数据。我设置了背景外设设置。和广告数据 advertisingData = [CBAdvertise
如果我有一组操作,我想根据特定条件在后台工作程序中运行,例如,我有 10 个条件 if(a) BackgroundWorker doA = new backgroundworker() if(
我想独立运行一个函数。从我调用的函数中,我想在不等待其他函数结束的情况下返回。 我试过用 threadind,但这会等待,结束。 thread = threading.Thread(target=my
我想在用户在线时立即执行一些任务,即使他在后台也是如此。我正在使用 Reachability 类来检查互联网。但是当我在后台时,这个类没有通知我。我知道有人早些时候问过这个问题,但没有找到任何解决方案
我在后台播放文本转语音时出现间歇性(哎呀!)问题,由 Apple Watch 触发。我已经正确设置了后台模式、AVSession 类别和 WatchKitExtensionRequest 处理程序。
我有一个相当复杂的程序,所以我不会在这里转储整个程序。这是一个简化版本: class Report { private BackgroundWorker worker; public
我有一个任务在 backgroundworker 中运行。单击开始按钮,用户将启动该过程,并获得一个取消按钮来取消处理。 当用户点击取消时,我想显示一个消息框“进程尚未完成,你想继续吗”。 这里我希望
我有一个按以下方式编码的脚本。我想将它作为后台/守护进程运行,但是一旦我启动脚本,如果我关闭它从程序运行的终端窗口终止。我需要做什么来保持程序运行 loop do pid = fork do
我正在制作一个使用 ActivityRecognition API 在后台跟踪用户 Activity 的应用,如果用户在指定时间段(例如 1 小时)内停留在同一个地方,系统就会推送通知告诉用户去散步.
当尝试使用 URLSession 的 dataTaskPublisher 方法发送后台请求时: URLSession(configuration: URLSessionConfiguration.ba
当我编译这段代码时,我得到了他的错误,对象引用设置为null,错误位置在Dowork中,argumenttest.valueone = 8; public partial class Form1 :
有什么方法可以使用最小化或不活动的应用程序吗?我可以打开我的应用程序,然后打开并使用另一个应用程序,然后按一个按钮来激活我的程序吗? 例如,打开我的应用程序,打开 Safari,按下按钮(F1 或任何
我的具体要求是一个在后台运行的应用程序,被通知显示器即将进入休眠状态或者设备已经或即将达到空闲超时 - 然后唤醒并执行一些(简短的)一段代码。 我在这里找到了有关应用程序被置于后台或暂停的通知的引用:
我有一个 LSUIElement 设置为 1 的应用程序。它有一个内置编辑器,因此我希望该应用程序在编辑器打开时出现在 Cmd+Tab 循环中。 -(void)stepIntoForegrou
我是一名优秀的程序员,十分优秀!