目前我正在编写一个应该在常规时间间隔拍照的相机应用程序。为此,我的活动创建了一个IntentService,它以所需的延迟启动TimerTask。我第一次启动我的应用程序一切正常。这些照片是在10秒的常规时间内拍摄的。但如果我暂停并恢复我的应用程序,则会更频繁地拍摄照片。
这是我的活动:
public class AndroidCameraExample extends Activity implements PictureTakenListener {
private static String CLASSTAG = "Android Surveillance Camera";
private Button captureButton;
private Context context;
private LinearLayout layoutForPreview;
private SurveillanceCamera camera;
// for calling the background service
private Intent backgroundServiceIntent = null;
// will send a notification if time has lapsed and we should
// take a new picture
private SurveillanceBroadcastReceiver receiver = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = this;
layoutForPreview = (LinearLayout) findViewById(R.id.camera_preview);
camera = new SurveillanceCamera(this, layoutForPreview);
captureButton = (Button) findViewById(R.id.button_capture);
captureButton.setOnClickListener(PictureCaptureListener);
camera.addPictureTakenListener(this);
startSurveillance();
}
private void startSurveillance() {
Settings.surveillanceIsActive = true;
camera.start();
startBackroundService();
registerBroadcastReceiver();
}
private void stopSurveillance() {
Settings.surveillanceIsActive = false;
if (receiver != null) {
unregisterReceiver(receiver);
receiver = null;
}
if (backgroundServiceIntent != null) {
stopService(backgroundServiceIntent);
backgroundServiceIntent = null;
}
camera.stop();
}
private void startBackroundService() {
if (isServiceRunning(SurveillanceBackgroundService.class)) {
Log.d(Settings.APPTAG, "The Service is already running");
}
if (backgroundServiceIntent == null) {
backgroundServiceIntent = new Intent(this, SurveillanceBackgroundService.class);
startService(backgroundServiceIntent);
}
}
private boolean isServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
private void registerBroadcastReceiver() {
if (receiver == null) {
IntentFilter filter = new IntentFilter(SurveillanceBroadcastReceiver.ACTION_RESP);
filter.addCategory(Intent.CATEGORY_DEFAULT);
receiver = new SurveillanceBroadcastReceiver();
registerReceiver(receiver, filter);
}
}
public void onResume() {
super.onResume();
startSurveillance();
}
@Override
protected void onPause() {
super.onPause();
stopSurveillance();
}
class SurveillanceBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
camera.takePicture();
}
}
我的服务
public class SurveillanceBackgroundService extends IntentService {
@Override
protected void onHandleIntent(Intent intent) {
Timer t = new Timer();
t.schedule(new TimerTask() {
@Override
public void run() {
notifyTimeLapsed();
}
}, 100, Settings.timeIntervall * 1000);
}
private void notifyTimeLapsed() {
Intent broadcastIntent = new Intent();
broadcastIntent.setAction(SurveillanceBroadcastReceiver.ACTION_RESP);
broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
sendBroadcast(broadcastIntent);
}
}
我已经检查过该应用程序暂停并且之后再次启动时服务没有运行(在后台运行),所以我没有看到为什么应该在恢复后更多地触发pictureTaking事件的原因。
我还使用一个小的包装类来处理相机,但我不认为这会导致问题。如果您需要编写建议任何解决方案的代码,我会在这里发布。
对此有何提示或帮助?
编辑:我覆盖onDestroy和onStart取消定时器并重新启动但问题保持不变。恢复后拍摄的照片比之前更多。
更新:如果我删除方法onStart,计时器似乎直接取消并且不会再次启动?我在方法中添加了一些Logger输出并获取此信息:
05-15 18:56:03.478:I / com.test.androidcameraexample(10061):SurveillanceBackgroundService onHandleIntent
05-15 18:56:03.498:I / com.test.androidcameraexample(10061):SurveillanceBackgroundService onDestroy
@Override
protected void onHandleIntent(Intent intent) {
if (t == null) {
t = new Timer();
t.schedule(new TimerTask() {
@Override
public void run() {
notifyTimeLapsed();
}
}, 100, Settings.timeIntervall * 1000);
}
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
if (t == null) {
t = new Timer();
t.schedule(new TimerTask() {
@Override
public void run() {
notifyTimeLapsed();
}
}, 100, Settings.timeIntervall * 1000);
}
}
@Override
public void onDestroy() {
super.onDestroy();
t.cancel();
t = null;
}
答案 0 :(得分:1)
我原来的答案是:
您需要拨打Timer.cancel()或TimerTask.cancel() 在服务创建的
Timer
或TimerTask
上,或者 计时器任务将继续在后台线程中运行。
然后我补充说:
为了让它可靠地运行,您可以指定一个
Intent
操作 用于启动计时器,以及用于停止计时器的另一个操作。
但是,在Timer
中存储IntentService
变量实际上存在一个很大(且微妙)的问题。 IntentService
创建自己的后台线程,如果队列中没有意图,它会很快自杀(在onHandleIntent ()
返回后) - 这也意味着你的Timer
值会丢失。因此,即使您有2个意图操作(用于启动和停止计时器),也无法保证停止操作可以访问原始Timer
值(因为它很可能创建一个品牌)新的IntentService
实例)!
因此,我建议您使用AlarmManager来安排定期警报。有关如何执行此操作的培训,请参阅here。