android:服务没有正常停止?

时间:2015-05-15 15:32:44

标签: android service camera task

目前我正在编写一个应该在常规时间间隔拍照的相机应用程序。为此,我的活动创建了一个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;
  }

1 个答案:

答案 0 :(得分:1)

我原来的答案是:

  

您需要拨打Timer.cancel()TimerTask.cancel()   在服务创建的TimerTimerTask上,或者   计时器任务将继续在后台线程中运行。

然后我补充说:

  

为了让它可靠地运行,您可以指定一个Intent操作   用于启动计时器,以及用于停止计时器的另一个操作。

但是,Timer中存储IntentService变量实际上存在一个很大(且微妙)的问题IntentService创建自己的后台线程,如果队列中没有意图,它会很快自杀(在onHandleIntent ()返回后) - 这也意味着你的Timer值会丢失。因此,即使您有2个意图操作(用于启动和停止计时器),也无法保证停止操作可以访问原始Timer值(因为它很可能创建一个品牌)新的IntentService实例)!

因此,我建议您使用AlarmManager来安排定期警报。有关如何执行此操作的培训,请参阅here