content: package com.abrenoch.hyperiongrabber.mobile;
  
  import android.app.ActivityManager;
  import android.content.BroadcastReceiver;
  import android.content.Context;
  import android.content.Intent;
  import android.content.IntentFilter;
  import android.os.Build;
  import android.os.Handler;
  import android.service.quicksettings.Tile;
  import android.service.quicksettings.TileService;
  import android.support.annotation.RequiresApi;
  import android.support.v4.app.TaskStackBuilder;
  import android.support.v4.content.LocalBroadcastManager;
  import android.text.TextUtils;
  import android.widget.Toast;
  
  import com.abrenoch.hyperiongrabber.common.BootActivity;
  import com.abrenoch.hyperiongrabber.common.HyperionScreenService;
  import com.abrenoch.hyperiongrabber.common.util.Preferences;
  
  @RequiresApi(api = Build.VERSION_CODES.N)
  public class HyperionGrabberTileService extends TileService {
      private final int REMOVE_LISTENER_DELAY = 1000 * 10; // 10 second delay to remove listener
      private static boolean mIsListening = false;
      private Handler mHandle = new Handler();
  
      private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
          @Override
          public void onReceive(Context context, Intent intent) {
              Tile tile = getQsTile();
              boolean running = intent.getBooleanExtra(HyperionScreenService.BROADCAST_TAG, false);
              String error = intent.getStringExtra(HyperionScreenService.BROADCAST_ERROR);
              tile.setState(running ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
              tile.updateTile();
              if (error != null) {
                  Toast.makeText(getBaseContext(), error, Toast.LENGTH_LONG).show();
              }
          }
      };
  
      @Override
      public void onStartListening() {
          super.onStartListening();
          mHandle.removeCallbacksAndMessages(null);
          if (!mIsListening) {
              LocalBroadcastManager.getInstance(this).registerReceiver(
                      mMessageReceiver, new IntentFilter(HyperionScreenService.BROADCAST_FILTER));
              mIsListening = true;
          }
          if (isServiceRunning()) {
              Intent intent = new Intent(this, HyperionScreenService.class);
              intent.setAction(HyperionScreenService.GET_STATUS);
              startService(intent);
          } else {
              Tile tile = getQsTile();
              tile.setState(Tile.STATE_INACTIVE);
              tile.updateTile();
          }
      }
  
      @Override
      public void onStopListening() {
          super.onTileRemoved();
          mHandle.postDelayed(unregisterReceiverRunner, REMOVE_LISTENER_DELAY);
      }
  
      @Override
      public void onDestroy() {
          super.onDestroy();
          mIsListening = false;
      }
  
      @Override
      public void onClick() {
          Tile tile = getQsTile();
          tile.updateTile();
          int tileState = tile.getState();
          if (tileState == Tile.STATE_ACTIVE) {
              Intent intent = new Intent(this, HyperionScreenService.class);
              intent.setAction(HyperionScreenService.ACTION_EXIT);
              startService(intent);
          } else {
              Runnable runner = () -> {
  
                  boolean setupStarted = startSetupIfNeeded();
  
                  if (!setupStarted){
                      final Intent i = new Intent(this, BootActivity.class);
                      i.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION
                              |Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
                              |Intent.FLAG_ACTIVITY_NO_HISTORY);
                      startActivity(i);
                  }
  
              };
              if (isLocked()) {
                  unlockAndRun(runner);
              } else {
                  runner.run();
              }
          }
      }
  
      private boolean isServiceRunning() {
          ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
          assert manager != null;
          for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
              if (HyperionScreenService.class.getName().equals(service.service.getClassName())) {
                  return true;
              }
          }
          return false;
      }
  
      private Runnable unregisterReceiverRunner = () -> {
          LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
          mIsListening = false;
      };
  
      public static boolean isListening() { return mIsListening; }
  
      /** Starts the Settings Activity if connection settings are missing
       *
       * @return true if setup was started
       */
      private boolean startSetupIfNeeded(){
          Preferences preferences = new Preferences(getApplicationContext());
          if (TextUtils.isEmpty(preferences.getString(R.string.pref_key_host, null)) || preferences.getInt(R.string.pref_key_port, -1) == -1){
              Intent settingsIntent = new Intent(this, SettingsActivity.class);
              settingsIntent.putExtra(SettingsActivity.EXTRA_SHOW_TOAST_KEY, SettingsActivity.EXTRA_SHOW_TOAST_SETUP_REQUIRED_FOR_QUICK_TILE);
              settingsIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  
              // Use TaskStackBuilder to make sure the MainActivity opens when the SettingsActivity is closed
              TaskStackBuilder.create(this)
                      .addNextIntentWithParentStack(settingsIntent)
                      .startActivities();
  
              Intent closeIntent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
              sendBroadcast(closeIntent);
  
              return true;
          }
  
          return false;
      }
  }
  