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; } }