KDP(電子出版)のメモ 急急如律令

Amazon Kindleダイレクト・パブリッシングでの電子出版や電子書籍の作成販売について、文章やイラストの作成や編集方法について書いています。

preferenceから設定値を取得する方法

設定値の取得コードを手動で書くのが面倒だった。メイン画面でどんな処理をさせるかを決めかねている。

あなた:

次のpreferenceから設定値を取得する方法

<!-- 表題 -->
<PreferenceCategory app:title="表題">
    <ListPreference
        app:key="title_type"
        app:title="表題の種類"
        app:entries="@array/title_type_names"
        app:entryValues="@array/title_type_values"
        android:defaultValue="0" />

    <CheckBoxPreference
        app:key="pub_first"
        app:title="先頭が発行者"
        android:defaultValue="false" />

    <CheckBoxPreference
        app:key="use_filename"
        app:title="ファイル名優先"
        android:defaultValue="false" />
</PreferenceCategory>

<!-- 表紙 -->
<PreferenceCategory app:title="表紙">
    <EditTextPreference
        app:key="max_cover_lines"
        app:title="最大行数"
        app:dialogTitle="画像注記の取得最大行数"
        android:defaultValue="10"
        android:inputType="number" />

    <ListPreference
        app:key="cover_mode"
        app:title="表紙設定"
        app:entries="@array/cover_options"
        app:entryValues="@array/cover_options_values"
        android:defaultValue="0" />

    <CheckBoxPreference
        app:key="use_cover_history"
        app:title="表紙履歴利用"
        android:defaultValue="true"
        app:summary="前回の表紙を利用。履歴は再起動で初期化されます。" />
</PreferenceCategory>

<!-- ページ出力 -->
<PreferenceCategory app:title="ページ出力">
    <CheckBoxPreference
        app:key="output_cover_page"
        app:title="表紙画像を出力"
        android:defaultValue="true" />

    <CheckBoxPreference
        app:key="output_title_page"
        app:title="表題ページを出力"
        android:defaultValue="true" />

    <ListPreference
        app:key="title_page_style"
        app:title="表題ページスタイル"
        app:entries="@array/title_page_styles"
        app:entryValues="@array/title_page_styles_values"
        android:defaultValue="middle" />

    <CheckBoxPreference
        app:key="output_toc"
        app:title="目次ページを出力"
        android:defaultValue="true" />

    <ListPreference
        app:key="toc_style"
        app:title="目次スタイル"
        app:entries="@array/toc_styles"
        app:entryValues="@array/toc_styles_values"
        android:defaultValue="vertical" />
</PreferenceCategory>

<!-- 出力ファイル設定 -->
<PreferenceCategory app:title="出力ファイル設定">

    <ListPreference
        app:key="file_extension"
        app:title="拡張子"
        app:summary="出力するファイルの拡張子"
        app:entries="@array/file_extension_entries"
        app:entryValues="@array/file_extension_values"
        android:defaultValue=".epub" />

    <SwitchPreferenceCompat
        app:key="use_title_for_filename"
        app:title="出力ファイル名に表題利用"
        android:defaultValue="true" />

    <SwitchPreferenceCompat
        app:key="overwrite_output"
        app:title="出力ファイル上書き"
        android:defaultValue="true" />
</PreferenceCategory>

ChatGPT:

この Preference XML ファイルに定義されている各設定項目の値を、Java または Kotlin のコードから取得する方法を以下に説明します。 主に SharedPreferences を使って取得します。

PreferenceFragmentCompat を使っている場合、次のように PreferenceManager から取得します:

val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())

またはカスタムの preferences.xml を使っているなら:

val sharedPreferences = requireContext().getSharedPreferences("your_pref_name", Context.MODE_PRIVATE)
val titleType = sharedPreferences.getString("title_type", "0")
val pubFirst = sharedPreferences.getBoolean("pub_first", false)
val useFilename = sharedPreferences.getBoolean("use_filename", false)
val maxCoverLines = sharedPreferences.getString("max_cover_lines", "10")?.toIntOrNull() ?: 10
val coverMode = sharedPreferences.getString("cover_mode", "0")
val useCoverHistory = sharedPreferences.getBoolean("use_cover_history", true)
val outputCoverPage = sharedPreferences.getBoolean("output_cover_page", true)
val outputTitlePage = sharedPreferences.getBoolean("output_title_page", true)
val titlePageStyle = sharedPreferences.getString("title_page_style", "middle")
val outputToc = sharedPreferences.getBoolean("output_toc", true)
val tocStyle = sharedPreferences.getString("toc_style", "vertical")
val fileExtension = sharedPreferences.getString("file_extension", ".epub")
val useTitleForFilename = sharedPreferences.getBoolean("use_title_for_filename", true)
val overwriteOutput = sharedPreferences.getBoolean("overwrite_output", true)
  • ListPreference の値は String 型で取得されます(entryValuesに基づく)。
  • CheckBoxPreference や SwitchPreferenceCompat は Boolean 型。
  • EditTextPreference は基本的に String 型で取得されるので、数値なら toIntOrNull() を使うと安全です。

ListPreference の値は String 型で取得されます(entryValuesに基づく)。

CheckBoxPreference や SwitchPreferenceCompat は Boolean 型。

EditTextPreference は基本的に String 型で取得されるので、数値なら toIntOrNull() を使うと安全です。

必要であれば、Java バージョンでも書き直しますよ!

あなた:

javaで書いて

ChatGPT:

了解です!先ほどの設定値取得コードを Java で書くと、以下のようになります。 PreferenceFragmentCompat などで SharedPreferences を使って値を取得する方法です。

SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext());

※ requireContext() は Fragment の中で使うことを想定しています。Activity の場合は this または getApplicationContext() を使ってください。

String titleType = sharedPreferences.getString("title_type", "0");
boolean pubFirst = sharedPreferences.getBoolean("pub_first", false);
boolean useFilename = sharedPreferences.getBoolean("use_filename", false);
int maxCoverLines;
try {
    maxCoverLines = Integer.parseInt(sharedPreferences.getString("max_cover_lines", "10"));
} catch (NumberFormatException e) {
    maxCoverLines = 10; // デフォルト値
}

String coverMode = sharedPreferences.getString("cover_mode", "0");
boolean useCoverHistory = sharedPreferences.getBoolean("use_cover_history", true);
boolean outputCoverPage = sharedPreferences.getBoolean("output_cover_page", true);
boolean outputTitlePage = sharedPreferences.getBoolean("output_title_page", true);
String titlePageStyle = sharedPreferences.getString("title_page_style", "middle");
boolean outputToc = sharedPreferences.getBoolean("output_toc", true);
String tocStyle = sharedPreferences.getString("toc_style", "vertical");
String fileExtension = sharedPreferences.getString("file_extension", ".epub");
boolean useTitleForFilename = sharedPreferences.getBoolean("use_title_for_filename", true);
boolean overwriteOutput = sharedPreferences.getBoolean("overwrite_output", true);
  • EditTextPreference(max_cover_lines など)は必ず String で取得されるため、Integer.parseInt() を使って変換します。
  • ListPreference の値も String 型で返ります。
  • CheckBoxPreference と SwitchPreferenceCompat は boolean 型で直接取得可能です。

EditTextPreference(max_cover_lines など)は必ず String で取得されるため、Integer.parseInt() を使って変換します。

ListPreference の値も String 型で返ります。

CheckBoxPreference と SwitchPreferenceCompat は boolean 型で直接取得可能です。

他にも保存処理(設定の書き込み)も必要でしたら、それもお手伝いします!

あなた:

sharedPreferencesが長いので、prefsに置き換えて

ChatGPT:

了解です!変数名を prefs に置き換えたバージョンを以下にまとめます。

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(requireContext());
String titleType = prefs.getString("title_type", "0");
boolean pubFirst = prefs.getBoolean("pub_first", false);
boolean useFilename = prefs.getBoolean("use_filename", false);
int maxCoverLines;
try {
    maxCoverLines = Integer.parseInt(prefs.getString("max_cover_lines", "10"));
} catch (NumberFormatException e) {
    maxCoverLines = 10;
}

String coverMode = prefs.getString("cover_mode", "0");
boolean useCoverHistory = prefs.getBoolean("use_cover_history", true);
boolean outputCoverPage = prefs.getBoolean("output_cover_page", true);
boolean outputTitlePage = prefs.getBoolean("output_title_page", true);
String titlePageStyle = prefs.getString("title_page_style", "middle");
boolean outputToc = prefs.getBoolean("output_toc", true);
String tocStyle = prefs.getString("toc_style", "vertical");
String fileExtension = prefs.getString("file_extension", ".epub");
boolean useTitleForFilename = prefs.getBoolean("use_title_for_filename", true);
boolean overwriteOutput = prefs.getBoolean("overwrite_output", true);

必要であれば、この設定値をまとめてクラスに格納する方法や、設定の保存処理(書き込み)も用意できます!

あなた:

設定値をlog.dで出力するコードを書いて

ChatGPT:

もちろんです!すべての設定値を Log.d() で出力する Java コードを以下に用意しました。 prefs を使い、タグは "AppPrefs" にしています(お好みで変更可)。

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(requireContext());

Log.d("AppPrefs", "=== 表題設定 ===");
Log.d("AppPrefs", "title_type: " + prefs.getString("title_type", "0"));
Log.d("AppPrefs", "pub_first: " + prefs.getBoolean("pub_first", false));
Log.d("AppPrefs", "use_filename: " + prefs.getBoolean("use_filename", false));

Log.d("AppPrefs", "=== 表紙設定 ===");
String maxCoverLinesStr = prefs.getString("max_cover_lines", "10");
int maxCoverLines;
try {
    maxCoverLines = Integer.parseInt(maxCoverLinesStr);
} catch (NumberFormatException e) {
    maxCoverLines = 10;
}
Log.d("AppPrefs", "max_cover_lines: " + maxCoverLines);
Log.d("AppPrefs", "cover_mode: " + prefs.getString("cover_mode", "0"));
Log.d("AppPrefs", "use_cover_history: " + prefs.getBoolean("use_cover_history", true));

Log.d("AppPrefs", "=== ページ出力 ===");
Log.d("AppPrefs", "output_cover_page: " + prefs.getBoolean("output_cover_page", true));
Log.d("AppPrefs", "output_title_page: " + prefs.getBoolean("output_title_page", true));
Log.d("AppPrefs", "title_page_style: " + prefs.getString("title_page_style", "middle"));
Log.d("AppPrefs", "output_toc: " + prefs.getBoolean("output_toc", true));
Log.d("AppPrefs", "toc_style: " + prefs.getString("toc_style", "vertical"));

Log.d("AppPrefs", "=== 出力ファイル設定 ===");
Log.d("AppPrefs", "file_extension: " + prefs.getString("file_extension", ".epub"));
Log.d("AppPrefs", "use_title_for_filename: " + prefs.getBoolean("use_title_for_filename", true));
Log.d("AppPrefs", "overwrite_output: " + prefs.getBoolean("overwrite_output", true));
  • Log.d() を使うには import android.util.Log; を忘れずに。
  • requireContext() を使っているため、このコードは Fragment 内で動かすことを前提にしています。Activity 内なら this または getApplicationContext() を使ってください。
  • 実行結果は Logcat の Debug レベルで表示されます。

Log.d() を使うには import android.util.Log; を忘れずに。

requireContext() を使っているため、このコードは Fragment 内で動かすことを前提にしています。Activity 内なら this または getApplicationContext() を使ってください。

実行結果は Logcat の Debug レベルで表示されます。

必要であれば Log.i() や Log.v() に変えることもできますし、ログ出力をまとめたヘルパークラスを作ることもできます!

あなた:

System.out.printにして

ChatGPT:

了解です!Log.d() をすべて System.out.print に置き換えたバージョンを以下に示します。 System.out.println() を使って改行付きで出力しています。

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(requireContext());

System.out.println("=== 表題設定 ===");
System.out.println("title_type: " + prefs.getString("title_type", "0"));
System.out.println("pub_first: " + prefs.getBoolean("pub_first", false));
System.out.println("use_filename: " + prefs.getBoolean("use_filename", false));

System.out.println("=== 表紙設定 ===");
String maxCoverLinesStr = prefs.getString("max_cover_lines", "10");
int maxCoverLines;
try {
    maxCoverLines = Integer.parseInt(maxCoverLinesStr);
} catch (NumberFormatException e) {
    maxCoverLines = 10;
}
System.out.println("max_cover_lines: " + maxCoverLines);
System.out.println("cover_mode: " + prefs.getString("cover_mode", "0"));
System.out.println("use_cover_history: " + prefs.getBoolean("use_cover_history", true));

System.out.println("=== ページ出力 ===");
System.out.println("output_cover_page: " + prefs.getBoolean("output_cover_page", true));
System.out.println("output_title_page: " + prefs.getBoolean("output_title_page", true));
System.out.println("title_page_style: " + prefs.getString("title_page_style", "middle"));
System.out.println("output_toc: " + prefs.getBoolean("output_toc", true));
System.out.println("toc_style: " + prefs.getString("toc_style", "vertical"));

System.out.println("=== 出力ファイル設定 ===");
System.out.println("file_extension: " + prefs.getString("file_extension", ".epub"));
System.out.println("use_title_for_filename: " + prefs.getBoolean("use_title_for_filename", true));
System.out.println("overwrite_output: " + prefs.getBoolean("overwrite_output", true));
  • Android アプリで System.out.println() を使うと、Logcat の「System.out」カテゴリに表示されます(あまり一般的ではないですが、開発中に使う分にはOK)。
  • 本番環境では通常 Log.d() を使います。

Android アプリで System.out.println() を使うと、Logcat の「System.out」カテゴリに表示されます(あまり一般的ではないですが、開発中に使う分にはOK)。

本番環境では通常 Log.d() を使います。

必要があれば、設定値をまとめて JSON 風に整形して出力することもできますよ!

あなた:

PreferenceFragmentCompatを使う意味は何

ChatGPT:

いい質問です!PreferenceFragmentCompat を使う意味は、Androidでユーザー設定画面(いわゆる「設定」UI)を簡単に作成・管理できる点にあります。 以下に詳しく説明しますね。

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <CheckBoxPreference
        android:key="example_checkbox"
        android:title="サンプルチェックボックス"
        android:defaultValue="true" />
</PreferenceScreen>

→ これを PreferenceFragmentCompat で読み込むだけで、即座に設定画面が完成します。

設定項目(CheckBoxPreference、ListPreference など)はユーザーが操作するたびに自動的に SharedPreferences に保存されます。 → コードで保存処理を書かなくてもOK。

PreferenceFragmentCompat を使うと、Androidのデフォルトスタイルに合った設定画面を作れます。 → 手動でレイアウトやロジックを作るより見た目も管理も楽。

Fragment として使えるので、他のUIと組み合わせたり、ViewPager, TabLayout, NavigationComponent とも連携しやすいです。

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <SwitchPreferenceCompat
        android:key="dark_mode"
        android:title="ダークモード"
        android:defaultValue="false" />
</PreferenceScreen>
public class SettingsFragment extends PreferenceFragmentCompat {
    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        setPreferencesFromResource(R.xml.preferences, rootKey);
    }
}

→ この2つだけで、設定画面が表示されて保存まで自動化されます。

  • UIを自前で Switch や EditText で作る必要あり
  • SharedPreferences への保存・読み込みを自前で実装する必要あり
  • レイアウトの調整やバージョン対応が面倒

UIを自前で Switch や EditText で作る必要あり

SharedPreferences への保存・読み込みを自前で実装する必要あり

レイアウトの調整やバージョン対応が面倒

方法 特徴
✅ PreferenceFragmentCompat を使う UI定義も保存も自動化。開発が超効率的。公式推奨。
❌ 使わない すべて手動でやる必要がある(柔軟性はあるが手間が大きい)

さらに応用で「変更を検知するリスナー」や「動的な有効/無効の切り替え」もできます。必要ならその実装も紹介しますよ!

あなた:

preferenceの取得をmainactivity内の関数で実装して

ChatGPT:

了解です!PreferenceFragmentCompat で設定した値を、MainActivity 内の関数で取得する方法を紹介します。

以下のように実装できます:

import android.content.SharedPreferences;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.preference.PreferenceManager;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // 設定値を取得・出力する関数を呼び出す
        printPreferenceValues();
    }

    private void printPreferenceValues() {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);

        System.out.println("=== 表題設定 ===");
        System.out.println("title_type: " + prefs.getString("title_type", "0"));
        System.out.println("pub_first: " + prefs.getBoolean("pub_first", false));
        System.out.println("use_filename: " + prefs.getBoolean("use_filename", false));

        System.out.println("=== 表紙設定 ===");
        String maxCoverLinesStr = prefs.getString("max_cover_lines", "10");
        int maxCoverLines;
        try {
            maxCoverLines = Integer.parseInt(maxCoverLinesStr);
        } catch (NumberFormatException e) {
            maxCoverLines = 10;
        }
        System.out.println("max_cover_lines: " + maxCoverLines);
        System.out.println("cover_mode: " + prefs.getString("cover_mode", "0"));
        System.out.println("use_cover_history: " + prefs.getBoolean("use_cover_history", true));

        System.out.println("=== ページ出力 ===");
        System.out.println("output_cover_page: " + prefs.getBoolean("output_cover_page", true));
        System.out.println("output_title_page: " + prefs.getBoolean("output_title_page", true));
        System.out.println("title_page_style: " + prefs.getString("title_page_style", "middle"));
        System.out.println("output_toc: " + prefs.getBoolean("output_toc", true));
        System.out.println("toc_style: " + prefs.getString("toc_style", "vertical"));

        System.out.println("=== 出力ファイル設定 ===");
        System.out.println("file_extension: " + prefs.getString("file_extension", ".epub"));
        System.out.println("use_title_for_filename: " + prefs.getBoolean("use_title_for_filename", true));
        System.out.println("overwrite_output: " + prefs.getBoolean("overwrite_output", true));
    }
}
  • PreferenceManager.getDefaultSharedPreferences(this) を使えば PreferenceFragmentCompat で保存された値をどこでも取得可能です。
  • この関数 printPreferenceValues() は任意のタイミングで呼び出せます(たとえばボタン押下時など)。
  • ログ出力ではなく画面に表示したい場合は TextView を使う方法に切り替えも可能です。

PreferenceManager.getDefaultSharedPreferences(this) を使えば PreferenceFragmentCompat で保存された値をどこでも取得可能です。

この関数 printPreferenceValues() は任意のタイミングで呼び出せます(たとえばボタン押下時など)。

ログ出力ではなく画面に表示したい場合は TextView を使う方法に切り替えも可能です。

必要であれば「設定値の変更を監視する」コードも用意できます!

あなた:

preferenceをmainactivityで使うときに更新された値を使う方法

ChatGPT:

いい質問です! PreferenceFragmentCompat でユーザーが変更した設定値を MainActivity で常に最新の状態で使う方法 は、大きく分けて以下の2通りがあります。

最も簡単・確実な方法です。 設定値を使うたびに最新の値を取得するようにすれば、常に更新後の値になります。

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean useCover = prefs.getBoolean("output_cover_page", true); // 毎回ここで取得
  • 確実に最新の値が取れる
  • コードがシンプル
  • 再起動や画面切り替えも問題なし

確実に最新の値が取れる

コードがシンプル

再起動や画面切り替えも問題なし

設定が変更された瞬間にコールバックされるので、リアルタイムで変数に反映したいときに使えます。

public class MainActivity extends AppCompatActivity {

    private SharedPreferences prefs;
    private SharedPreferences.OnSharedPreferenceChangeListener listener;

    private boolean useCoverPage; // 変更時に更新する変数

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        prefs = PreferenceManager.getDefaultSharedPreferences(this);

        // 初期値を取得
        useCoverPage = prefs.getBoolean("output_cover_page", true);

        // リスナー登録
        listener = (sharedPreferences, key) -> {
            if ("output_cover_page".equals(key)) {
                useCoverPage = sharedPreferences.getBoolean(key, true);
                System.out.println("output_cover_page changed: " + useCoverPage);
            }
        };
        prefs.registerOnSharedPreferenceChangeListener(listener);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (prefs != null && listener != null) {
            prefs.unregisterOnSharedPreferenceChangeListener(listener);
        }
    }
}
方法 特徴
✅ 方法①: 毎回取得 簡単、確実、ミスが少ない。おすすめ。
✅ 方法②: リスナー登録 設定変更を即検知したいときに便利(リアルタイム更新など)。
  • 「今の設定値を使いたい」→ 方法①がベスト
  • 「設定が変わった瞬間に何かしたい」→ 方法②を使う

「今の設定値を使いたい」→ 方法①がベスト

「設定が変わった瞬間に何かしたい」→ 方法②を使う

必要であれば、ボタンや処理単位での具体例も追加できますよ!