質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.62%

  • Android

    6394questions

    Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

[Android] Toggleボタンの状態の保持

解決済

回答 1

投稿

  • 評価
  • クリップ 2
  • VIEW 3,886

noriyo_tcp

score 11

toggleボタンを押すとサービス開始(タイマー作動、ボタンの表記はResetになる)、またボタンを押すとサービス停止(タイマーリセット)というアプリを作っているのですが、バックグラウンドからアプリに復帰したときに、toggleボタンが元の状態に戻っていまいます(タイマーは動作を続けている)
どうすればボタンの状態を保持できるのでしょうか?

以下がコードです(一部省略)

MainActivity.java
// (一部省略)
import android.app.Activity;
import android.content.Intent;
// 以下必要なものをimport

public class MainActivity extends Activity implements OnCheckedChangeListener {

  static TextView timer;
  static ToggleButton toggle;
  private static long settingTime = 60000;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    timer = (TextView) findViewById(R.id.timer);
    toggle = (ToggleButton) findViewById(R.id.toggleButton1);

    // 初期時間設定
    showTimer(getSettingTime());

    // リスナ登録
    toggle.setOnCheckedChangeListener(this);
  }

  TimerService timerTask = new TimerService();
  private Intent timerIntent;

  @Override
  public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
      // サービスを開始か停止
      if (isChecked == true) {
        Toast.makeText(this, "Start", Toast.LENGTH_SHORT).show();
        // Start service
        startService();
      } else {
        // Stop service
        stopService(timerIntent);
        // 設定した時間にリセット
        showTimer(getSettingTime());
    }
}

  public void startService() {
    // Serviceに設定時間を送ってサービス開始
    timerIntent = new Intent(MainActivity.this, TimerService.class);
    timerIntent.putExtra("settingTime", getSettingTime());

    startService(timerIntent);
  }
}

TimerService.java
// (一部省略)
import android.app.Service;
import android.content.Intent;
import android.os.CountDownTimer;
import android.os.IBinder;
import android.widget.Toast;

public class TimerService extends Service {
  protected MyCountDownTimer cdt;

  @Override
  public IBinder onBind(Intent arg0) {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public void onCreate() {
    // TODO Auto-generated method stub
    super.onCreate();
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    // タイマーのインスタンス生成&スタート
    cdt = new MyCountDownTimer(intent.getExtras().getLong("settingTime"), 500);
    cdt.start();

    return super.onStartCommand(intent, flags, startId);
  }

  @Override
  public void onDestroy() {
    // タイマーインスタンスのキャンセル&破棄
    cdt.cancel();
    cdt = null;

    super.onDestroy();
  }

  public class MyCountDownTimer extends CountDownTimer {
    public MyCountDownTimer(long millisInFuture, long countDownInterval) {
      super(millisInFuture, countDownInterval);
      MainActivity.showTimer(millisInFuture);
  }

    @Override
    public void onFinish() {
      MainActivity.timer.setText("0:00");
      Toast.makeText(getApplicationContext(), "Finished!", Toast.LENGTH_SHORT).show();
      // 設定時間にリセット
      MainActivity.showTimer(MainActivity.getSettingTime());
      // トグルボタンをfalse
      MainActivity.toggle.setChecked(false);
      // Stop service
      stopSelf();
    }

    @Override
    public void onTick(long millisUntilFinished) {
      // 残り時間表示
      MainActivity.showTimer(millisUntilFinished);
    }
  }
}

試してみたのは
  • SharedPreferences(トグルボタンの状態を保持したい)
  • MainActivityのonResume()にいろいろ記述(ライフサイクルがよくわかってない)
などですが、うまくいきません。
Logを仕込んでみたところ、アプリがバックグラウンドに回ると、onPause() -> onStop()と状態遷移して、そこから復帰するときにonCreate() -> onStart() -> onResume()と遷移しているのは分かったのですけど、そこでデフォルトに戻ってしまっているのかな?と。(xmlでのToggleButtonの属性にandroid:checked="false"と記述している)
setChecked(Boolean)で指定してもコールバックメソッドを呼んでしまうので、どうしたものかなと。
長くなりましたが、とにかくトグルボタンの状態を保持したいのです。
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+2

onCreateのListener登録の前にsetCheckedで状態を設定してあげるのはどうでしょうか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2014/07/31 14:29

    ホームボタンで閉じたあとの復帰はいいのですけど、バックボタンからの復帰ではうまくいきませんね。ふむー。

    キャンセル

  • 2014/07/31 15:53

    簡単なサンプルを作成して試したのですが、ToggleButtonをONにして他のアプリを起動しバックボタンで戻ってもToggleButtonはONのままです。
    Activityが破棄されなければ状態は残っていると思います。
    他でToggleButtonに値を設定している箇所などありませんか?

    キャンセル

  • 2014/07/31 18:11

    Log.v(<ライフサイクル名>, toggle.isChecked())でチェック状態を取得してみましたが、

    // アプリ起動
    onCreate(890): toggle is false
    onStart(890): toggle is false
    onResume(890): toggle is false
    // 他のアプリ起動から戻るボタン、アイコンクリックで復帰
    onPause(890): toggle is true
    onStop(890): toggle is true
    onStart(890): toggle is true
    onResume(890): toggle is true
    // 戻るボタンで閉じてからアイコンクリックでの復帰
    onPause(890): toggle is true
    onStop(890): toggle is true
    onDestroy(890): toggle is true
    onCreate(890): toggle is false
    onStart(890): toggle is false
    onResume(890): toggle is false

    onDestroyされても状態は維持されているようですが、その後のonCreate()で結局元に戻ってしまっているようです。
    閉じる前に状態を保持して、onCreate()の時にそれを読み込めばいいんですかね?
    他の箇所では値を設定してないんですよねー。

    キャンセル

  • 2014/07/31 18:22

    最初の解答と同じになってしまいますが、onCreateのListener登録の前にサービスから今の状態を取得してsetCheckedに設定すればいいと思います。

    キャンセル

  • 2014/08/01 13:15

    Bundleを用意して
    public static Bundle outState = new Bundle();

    onResume()で
    toggle.setChecked(outState.getBoolean("toggleKey", toggle.isChecked()));
    toggle.setOnCheckedChangeListener(this);
    onCreate()でも同様の記述をして、

    onPause()で
    outState.putBoolean("toggleKey", toggle.isChecked());
    toggle.setOnCheckedChangeListener(this);
    としました。

    stopService()もstartService()と同様に、
    public void stopService() {
    timerIntent = new Intent(MainActivity.this, TimerService.class);
    stopService(timerIntent);
    }
    を作って、リスナ側からは引数無しでそのまま呼び出すという形にしました。
    これでバックボタンからの復帰でもトグルボタンの状態が維持されてはいます(ごくたまにresetを押しても表示が戻らない現象がありますが・・・)
    一応onSaveInstanceStateとonRestoreInstanceStateも用意しましたが、あるときとないときとのちがいはよくわかりません(挙動は変わりない・・・ように見える)

    いやはやお手数をおかけしました・・・。

    参考記事
    http://stackoverflow.com/questions/12334991/preserving-toggle-button-state-on-my-activity

    キャンセル

  • 2014/08/01 17:24

    解決?されたようで良かったです。
    そしてあまりお役にたてなくてすみませんでした。

    最後に
    Serviceが状態を把握しているわけですから、Bundleに保持するのでなくServiceから取得する方がスマートだと思います。
    また、Service側でカウントダウンが終了した場合にトグルの状態の不整合が起こるように思えます。

    Service取得について以下のサイト記事が参考になるかと思います
    http://www.atmarkit.co.jp/ait/articles/0906/18/news102.html

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.62%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 受付中

    ホームボタン押下からのアプリ復帰について

    現在、Activityが2つあるアプリケーションの開発を行っております。 Activity1→(遷移)→Activity2 Activity2を表示させた状態でホームボタンを押下

  • 解決済

    Checkbox2がダメだった時にはCheckbox3がtrueかどうかを確認するプログラムを書きた...

    Checkbox2がダメだった時にはCheckbox3がtrueかどうかを確認するプログラムを書きたいのですが import android.app.Activity; imp

  • 解決済

    Android 開発 Caldroid ボタン操作について質問

    現在、カレンダーアプリを作っています。 そしてGitHub上にある roomoramaさんが作った Caldroid というプロジェクトをGradle 経由でインポートして使ってい

  • 解決済

    他クラスからTextViewを変更したい

    前提・実現したいこと Androidでアプリ開発をしています。 ServiceからActivityのTextViewに文字列を渡す機能を実装しようとしているのですが 以下のエラーメ

  • 解決済

    androidstudio 色検出

    androidstudioで色検出をしようとしています。このサイトのコードをほぼほぼコピペしたのですが FdActivity.javaでonCreateOptionsMenuの中の

  • 解決済

    android opencv で色検出

    私はandroidstudioでアプリ開発を行なっており今opencvを使っています。 フレームの中に入っている緑の色をしている領域の中で一番面積が大きいものを選び出し、その輪郭を

  • 解決済

    ボタンでの加速度とジャイロセンサのCSV保存

    前提・実現したいこと Androidのアプリをつくっていて、加速度とジャイロセンサの値を時刻とともにCSVで実機に保存したいのですが、うまくいかず困っています。また、START S

  • 解決済

    android opencvで輪郭描画

    私はandroidstudioでアプリ開発を行っています。 実現したいこと opencvで赤い色を検知して赤色を白に、それ以外を黒にしてそのあとに赤い物の輪郭の中心座標を返した

同じタグがついた質問を見る

  • Android

    6394questions

    Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

関連ワード: android トグルボタン