MyTracks 読み (16)

続きはどこから開始なのやら。とりあえず

  • PeriodicTaskExecuter クラス掘削
  • TripStatistics クラスについて
  • showNotification メソド
  • registerLocationListener メソド
  • splitManager.restore メソド
  • signalManager.restore メソド

あとは、onLocationChanged で何が行なわれてて unregisterLocationListener でどんな後処理がされているのか。あ、違うな。オプションメニューのレコード停止な処理から見ないと駄目なのか。そーゆー意味ではトラックを確認する処理についても掘削が必要ですな。

とゆー事で

掘削開始。ええと生かなナニから。

      if (executer == null) {
        SafeStatusAnnouncerTask announcer = new SafeStatusAnnouncerTask(this);
        executer = new PeriodicTaskExecuter(announcer, this);
      }

executer の型は PeriodicTaskExecuter ッスね。

  private PeriodicTaskExecuter executer;

で、コンストラクタの定義が以下です。

  public PeriodicTaskExecuter(PeriodicTask task,
                              TrackRecordingService service) {
    this.task = task;
    this.service = service;
  }

SafeStatusAnnouncerTask クラスは PeriodicTask のサブクラスなのかな。ええと

            executer.scheduleTask(announcementFrequency * 60000);

なソレを掘るのが先なのか、PeriodicTask 云々を見てみるのが先なのか。それ以前にそもそも無駄な部分を掘ってる気がしてならない。とりあえず SafeStatusAnnouncerTask の定義を見てみたら PeriodicTask のサブクラスでした。

public class SafeStatusAnnouncerTask implements PeriodicTask {

あ、PeriodicTask は interface ですね。

  • void start()
  • void run(TrackRecordingService)
  • void shutdown()

を override しないといけない模様。それは良いとして scheduleTask メソド的には引数で渡される interval を云々しつつ、最終的には

    timer.scheduleAtFixedRate(new PeriodicTimerTask(), start, interval);

という事になるのか。PeriodicTimerTask クラスは PeriodicTaskExecuter の内部クラスとして定義されてて以下。

  private class PeriodicTimerTask extends TimerTask {
    @Override
    public void run() {
      task.run(service);
    }
  }

基本的には start 以降 interval おきに上記の run が呼び出されるという事か。ええと、SafeStatusAnnouncerTask の run に TrackRecordingService が渡される、と見て良いのかな。
ええと、SafeStatusAnnouncerTask の run が以下。

  public void run(TrackRecordingService service) {
    announcer.run(service);
  }

で、announcer 属性はコンストラクタで生成されてて以下です。

  public SafeStatusAnnouncerTask(Context context) {
    announcer = new StatusAnnouncerTask(context);
  }

StatusAnnouncerTask の run の定義は、というと以下な模様。

  /**
   * Announces the trip status.
   */
  @Override
  public void run(TrackRecordingService service) {
    if (ttsStatus != TextToSpeech.SUCCESS && tts != null) {
      Log.e(MyTracksConstants.TAG, "StatusAnnouncer Tts not initialized.");
      return;
    }

    if (service == null || service.getTripStatistics() == null) {
      Log.e(MyTracksConstants.TAG, "StatusAnnouncer stats not initialized.");
      return;
    }

    String announcement = getAnnouncement(service.getTripStatistics());
    Log.d(MyTracksConstants.TAG, "Announcement: " + announcement);
    tts.speak(announcement, TextToSpeech.QUEUE_FLUSH, null);
  }

tts という属性ですがコンストラクタにてオブジェクトが生成されている模様です。

  public StatusAnnouncerTask(Context context) {
    this.context = context;
    this.stringUtils = new StringUtils(context);

    tts = new TextToSpeech(context, this);

この TextToSpeech って android なクラスみたい。

import android.speech.tts.TextToSpeech;

テキスト読み上げ、って微妙なのでスルーします。測位情報の保存と全然関係ないし。

TripStatistics

これも読み上げに関連するナニのはずなのでスルー。

showNotification メソド

以下なコメントから、ここもスルーします。

  /**
   * Shows the notification message and icon in the notification bar.
   */
  public void showNotification() {

registerLocationListener メソド

キモの部分のみ以下に。

      long desiredInterval = locationListenerPolicy.getDesiredPollingInterval();
      locationManager.requestLocationUpdates(
          MyTracksConstants.GPS_PROVIDER, desiredInterval,
          locationListenerPolicy.getMinDistance(),
          // , 0 /* minDistance, get all updates to properly time pauses */
          TrackRecordingService.this);
      currentRecordingInterval = desiredInterval;

ええと、locationListenerPolicy という変数は何だ、と言いつつ定義が以下。

  /**
   * The policy used to decide how often we should request gps updates.
   */
  private LocationListenerPolicy locationListenerPolicy =
      new AbsoluteLocationListenerPolicy(0);

うーん。何だこれは。と思ったら MyTracks ローカルなクラスみたい。ええと LocationListenerPolicy は interface な模様。

  • long getDesiredPollingInterval()
  • int getMinDistance()
  • void updateIdleTIme(long)

がナニ。AbsoluteLocationListenerPolicy クラスは、というと結構テキトーな作りだなぁ。一部ですが以下に引用。

/**
 * This is a simple location listener policy that will always dictate the same
 * polling interval.
 *
 * @author Sandor Dornbush
 */
public class AbsoluteLocationListenerPolicy implements LocationListenerPolicy {

  /**
   * The interval to request for gps signal.
   */
  private final long interval;

  /**
   * @param interval The interval to request for gps signal
   */
  public AbsoluteLocationListenerPolicy(final long interval) {
    this.interval = interval;
  }

  /**
   * @return The interval given in the constructor
   */
  public long getDesiredPollingInterval() {
    return interval;
  }

  /**
   * Discards the idle time.
   */
  public void updateIdleTime(long idleTime) {
  }

  /**
   * Returns the minimum distance between updates.
   * Get all updates to properly measure moving time.
   */
  public int getMinDistance() {
    return 0;
  }
}

という事は desiredInterval の値は 0 ですな。ええと requestLocationUpdates の引数ですが

public void requestLocationUpdates (String provider, 
                                    long minTime, 
				    float minDistance, 
				    LocationListener listener)

というナニがあります。時間および距離についてどの程度 {経過|移動} したら update か、なナニを引数に渡すんですか。ちなみにこの例 (MyTracks) では両方 0 になります。
最後に currentRecordingInterval という属性に desiredInterval の値をセットしてます。
これで onLocationChanged な callback が呼び出される準備ができたはず。

splitManager.restore メソドとsignalManager.restore メソド

ええと splitManger という属性は SplitManager 型です。service ディレクトリに定義。
また、signalManager という属性は TaskExecuterManager 型です。service ディレクトリに定義。
ちょっとここ、ポイント高そうなのでとりあえずエントリ投入します。元気があれば続きを掘ります。