gt:         spinnerVoice = view.findViewById(R.id.spinnerVoice);
context: package fr.gaulupeau.apps.Poche.tts;
  
  import android.app.Activity;
  import android.app.PendingIntent;
  import android.content.BroadcastReceiver;
  import android.content.ComponentName;
  import android.content.Context;
  import android.content.Intent;
  import android.content.IntentFilter;
  import android.content.ServiceConnection;
  import android.content.res.Configuration;
  import android.media.AudioManager;
  import android.os.Bundle;
  import android.os.Handler;
  import android.os.IBinder;
  import android.support.v4.media.session.MediaControllerCompat;
  import android.support.v4.media.session.MediaSessionCompat;
  import android.support.v4.media.session.PlaybackStateCompat;
  import android.text.TextUtils;
  import android.util.Log;
  import android.view.LayoutInflater;
  import android.view.View;
  import android.view.ViewGroup;
  import android.widget.AdapterView;
  import android.widget.ArrayAdapter;
  import android.widget.CheckBox;
  import android.widget.ImageButton;
  import android.widget.ImageView;
  import android.widget.SeekBar;
  import android.widget.Spinner;
  import android.widget.TextView;
  import android.widget.Toast;
  
  import androidx.annotation.NonNull;
  import androidx.annotation.Nullable;
  import androidx.annotation.StringRes;
  import androidx.fragment.app.Fragment;
  
  import java.text.NumberFormat;
  import java.util.ArrayList;
  import java.util.List;
  import java.util.Locale;
  
  import fr.gaulupeau.apps.InThePoche.R;
  import fr.gaulupeau.apps.Poche.App;
  import fr.gaulupeau.apps.Poche.data.Settings;
  import fr.gaulupeau.apps.Poche.data.dao.entities.Article;
  import fr.gaulupeau.apps.Poche.ui.MainActivity;
  import fr.gaulupeau.apps.Poche.ui.ReadArticleActivity;
  import fr.gaulupeau.apps.Poche.utils.IntentUtils;
  
  /**
   * Text To Speech (TTS) User Interface.
   */
  public class TtsFragment extends Fragment {
  
      /* AudioManager.VOLUME_CHANGED_ACTION */
      private static final String VOLUME_CHANGED_ACTION = "android.media.VOLUME_CHANGED_ACTION";
  
      private static final String TAG = TtsFragment.class.getSimpleName();
  
      private static final String PARAM_AUTOPLAY = "autoplay";
  
      private static final String STATE_MEDIA_SESSION_TOKEN = "media_session_token";
  
      private static final String METADATA_ALBUM = "wallabag";
  
      private static final float MAX_TTS_SPEED = 4.0F;
      private static final float MAX_TTS_PITCH = 2.0F;
  
      // TODO: fix: unreliable caching (especially initialization)
      private static final TtsData TTS_DATA = new TtsData();
  
      private Settings settings;
      private NumberFormat percentFormat;
  
      private BroadcastReceiver volumeChangeReceiver;
  
      private PendingIntent notificationPendingIntent;
  
      private View viewTtsOption;
      private ImageButton btnTtsPlayStop;
      private SeekBar seekBarTtsSpeed;
      private SeekBar seekBarTtsPitch;
      private SeekBar seekBarTtsVolume;
      private SeekBar seekBarTtsSleep;
      private TextView textViewTtsSpeed;
      private TextView textViewTtsPitch;
      private TextView textViewTtsVolume;
      private TextView textViewTtsSleep;
      private Spinner spinnerLanguage;
      private Spinner spinnerVoice;
      private ArrayAdapter<String> spinnerLanguageAdapter;
      private ArrayAdapter<String> spinnerVoiceAdapter;
      private AudioManager audioManager;
      private MediaControllerCompat.Callback mediaCallback;
  
      private boolean dontStopTtsService;
  
      private Activity activity;
      private TtsHost ttsHost;
  
      private MediaSessionCompat.Token mediaSessionToken;
      private MediaControllerCompat mediaController;
  
      private TtsService ttsService;
      private ServiceConnection serviceConnection;
  
      private Integer articleId;
      private String artist = "";
      private String title = "";
      private String previewPicture;
  
      private String languageToSelect;
  
      private WebViewText webViewText;
  
      private TtsData.VoiceInfo selectedVoiceInfo;
  
      private boolean initialized;
      private boolean reinitDocument;
      private boolean documentLoaded;
      private boolean documentParsed;
      private boolean setToServicePending;
  
      public static TtsFragment newInstance(boolean autoplay) {
          TtsFragment fragment = new TtsFragment();
          Bundle args = new Bundle();
          args.putBoolean(PARAM_AUTOPLAY, autoplay);
          fragment.setArguments(args);
          return fragment;
      }
  
      public TtsFragment() {
          settings = App.getSettings();
  
          percentFormat = NumberFormat.getPercentInstance();
          percentFormat.setMaximumFractionDigits(0);
  
          volumeChangeReceiver = new BroadcastReceiver() {
              @Override
              public void onReceive(Context context, Intent intent) {
                  if (VOLUME_CHANGED_ACTION.equals(intent.getAction())) {
                      updateVolumeDisplay();
                  }
              }
          };
      }
  
      @Override
      public void onAttach(@NonNull Context context) {
          super.onAttach(context);
          Log.d(TAG, "onAttach()");
  
          activity = (Activity) context;
          ttsHost = ((ReadArticleActivity) activity).getTtsHost();
  
          if (webViewText != null) webViewText.setTtsHost(ttsHost);
  
          activity.setVolumeControlStream(AudioManager.STREAM_MUSIC);
  
          activity.registerReceiver(volumeChangeReceiver, new IntentFilter(VOLUME_CHANGED_ACTION));
      }
  
      @Override
      public void onDetach() {
          super.onDetach();
          Log.d(TAG, "onDetach()");
  
          activity.unregisterReceiver(volumeChangeReceiver);
          activity = null;
  
          ttsHost = null;
          if (webViewText != null) webViewText.setTtsHost(null);
      }
  
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          Log.d(TAG, "onCreate()");
  
          if (savedInstanceState != null) {
              mediaSessionToken = savedInstanceState.getParcelable(STATE_MEDIA_SESSION_TOKEN);
          }
  
          Intent mainFocusIntent = new Intent(Intent.ACTION_MAIN);
          mainFocusIntent.setClass(activity, MainActivity.class);
          mainFocusIntent.addCategory(Intent.CATEGORY_LAUNCHER);
          notificationPendingIntent = PendingIntent.getActivity(
                  activity, 0, mainFocusIntent, IntentUtils.FLAG_IMMUTABLE);
  
          TTS_DATA.init(activity, this::startActivityForResult);
      }
  
      @Override
      public void onDestroy() {
          super.onDestroy();
          Log.d(TAG, "onDestroy()");
      }
  
      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
          Log.d(TAG, "onCreateView()");
  
          View view = inflater.inflate(R.layout.fragment_tts, container, false);
  
          viewTtsOption = view.findViewById(R.id.viewTTSOptions);
          if (!settings.isTtsOptionsVisible()) {
              viewTtsOption.setVisibility(View.GONE);
          }
          btnTtsPlayStop = view.findViewById(R.id.btnTTSPlayPause);
          btnTtsPlayStop.setOnClickListener(v -> playPauseCommand());
  
          ImageButton btnTtsFastRewind = view.findViewById(R.id.btnTTSFastRewind);
          btnTtsFastRewind.setOnClickListener(v -> rewindCommand());
  
          ImageButton btnTtsFastForward = view.findViewById(R.id.btnTTSFastForward);
          btnTtsFastForward.setOnClickListener(v -> fastForwardCommand());
  
          ImageButton btnTtsOptions = view.findViewById(R.id.btnTTSOptions);
          btnTtsOptions.setOnClickListener(v -> onTtsOptionsClicked());
  
          CheckBox checkboxTtsAutoplayNext = view.findViewById(R.id.chkbxTTSAutoplayNext);
          checkboxTtsAutoplayNext.setChecked(settings.isTtsAutoplayNext());
          checkboxTtsAutoplayNext.setOnCheckedChangeListener((buttonView, isChecked) -> {
              settings.setTtsAutoplayNext(isChecked);
              if (isChecked) {
                  showToastMessage(R.string.ttsAutoplayNextArticle);
              }
          });
  
          ImageView imgViewTtsAutoplayNext = view.findViewById(R.id.imgviewTTSAutoplayNext);
          imgViewTtsAutoplayNext.setOnClickListener(v -> checkboxTtsAutoplayNext.toggle());
  
          textViewTtsSpeed = view.findViewById(R.id.textViewTTSSpeed);
          textViewTtsPitch = view.findViewById(R.id.textViewTTSPitch);
          textViewTtsVolume = view.findViewById(R.id.textViewTTSVolume);
          textViewTtsSleep = view.findViewById(R.id.textViewTTSSleep);
  
          seekBarTtsSpeed = view.findViewById(R.id.seekBarTTSSpeed);
          seekBarTtsSpeed.setMax(Integer.MAX_VALUE);
          seekBarTtsSpeed.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
              boolean isTouchTracking;
              int initialProgress;
  
              @Override
              public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                  textViewTtsSpeed.setText(percentFormat.format(getSpeedBarValue()));
                  if (!isTouchTracking) {
                      ttsSetSpeedFromSeekBar();
                  }
              }
  
              @Override
              public void onStartTrackingTouch(SeekBar seekBar) {
                  initialProgress = seekBarTtsSpeed.getProgress();
                  isTouchTracking = true;
              }
  
              @Override
              public void onStopTrackingTouch(SeekBar seekBar) {
                  isTouchTracking = false;
                  if (seekBarTtsSpeed.getProgress() != initialProgress) {
                      ttsSetSpeedFromSeekBar();
                  }
              }
          });
          seekBarTtsSpeed.setProgress((int) (
                  settings.getTtsSpeed() * seekBarTtsSpeed.getMax() / MAX_TTS_SPEED));
  
          seekBarTtsPitch = view.findViewById(R.id.seekBarTTSPitch);
          seekBarTtsPitch.setMax(Integer.MAX_VALUE);
          seekBarTtsPitch.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
              boolean isTouchTracking;
              int initialProgress;
  
              @Override
              public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                  textViewTtsPitch.setText(percentFormat.format(getPitchBarValue()));
                  if (!isTouchTracking) {
                      ttsSetPitchFromSeekBar();
                  }
              }
  
              @Override
              public void onStartTrackingTouch(SeekBar seekBar) {
                  initialProgress = seekBarTtsPitch.getProgress();
                  isTouchTracking = true;
              }
  
              @Override
              public void onStopTrackingTouch(SeekBar seekBar) {
                  isTouchTracking = false;
                  if (seekBarTtsPitch.getProgress() != initialProgress) {
                      ttsSetPitchFromSeekBar();
                  }
              }
          });
          seekBarTtsPitch.setProgress((int) (
                  settings.getTtsPitch() * seekBarTtsPitch.getMax() / MAX_TTS_PITCH));
  
          seekBarTtsSleep = view.findViewById(R.id.seekBarTTSSleep);
          seekBarTtsSleep.setMax(Integer.MAX_VALUE);
  
          audioManager = (AudioManager) activity.getSystemService(Context.AUDIO_SERVICE);
  
          seekBarTtsVolume = view.findViewById(R.id.seekBarTTSVolume);
          seekBarTtsVolume.setMax(audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC));
          updateVolumeDisplay();
  
          seekBarTtsVolume.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
              @Override
              public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                  if (fromUser) {
                      audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, progress, 0);
                      textViewTtsVolume.setText(percentFormat.format(
                              (1.0 * progress) / seekBar.getMax()));
                  }
              }
  
              @Override
              public void onStartTrackingTouch(SeekBar seekBar) {}
  
              @Override
              public void onStopTrackingTouch(SeekBar seekBar) {}
          });
  
          spinnerLanguage = view.findViewById(R.id.spinnerLanguage);
          spinnerLanguageAdapter = new ArrayAdapter<>(activity,
                  android.R.layout.simple_spinner_item, new ArrayList<>());
          spinnerLanguageAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
          spinnerLanguage.setAdapter(spinnerLanguageAdapter);
  
  