Skip to content

Commit

Permalink
Pushing the Power button will stop FakeStandby now
Browse files Browse the repository at this point in the history
  • Loading branch information
JonasBernard committed Sep 9, 2020
1 parent bc7b391 commit 081df2d
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 19 deletions.
26 changes: 20 additions & 6 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
xmlns:tools="http://schemas.android.com/tools"
package="android.jonas.fakestandby">

<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

<application
android:allowBackup="true"
android:icon="@mipmap/app_icon_final"
Expand All @@ -11,9 +14,10 @@
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">

<activity android:name=".onboarding.OnBoardingActivity"
<activity
android:name=".onboarding.OnBoardingActivity"
android:label="Welcome to FakeStandby" />

<activity
android:name=".settings.SettingsActivity"
android:icon="@drawable/app_icon_adaptive"
Expand All @@ -25,18 +29,30 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".settings.LicenseActivity"
<activity
android:name=".settings.LicenseActivity"
android:label="@string/license_activity_title">
<intent-filter>
<action android:name="android.jonas.fakestandby.license" />

<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>

<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-8850353377499245~3510896955" />

<receiver
android:name=".service.PhoneLockReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.SCREEN_OFF"/>
<action android:name="android.intent.action.SCREEN_ON" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>

<service
android:name=".service.AccessibilityOverlayService"
android:label="@string/accessibility_service_label"
Expand All @@ -60,6 +76,4 @@
</service>
</application>

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.PixelFormat;
import android.jonas.fakestandby.permissions.OverlayPermissionRequiredDialog;
import android.jonas.fakestandby.settings.NoCloseOptionSelectedNotification;
Expand Down Expand Up @@ -33,6 +34,8 @@ public class AccessibilityOverlayService extends AccessibilityService {

public static boolean running = false;

private PhoneLockReceiver phoneLockReceiver;

// Some objects that make the rendering possible
static WindowManager windowManager;
static WindowManager.LayoutParams layoutParams;
Expand All @@ -54,15 +57,22 @@ public class AccessibilityOverlayService extends AccessibilityService {
// INITIALIZED Set to when the overlay is ready.
// |
// v
// ADDED <--- Set to after the overlay view component was added to the screen.
// SHOWING | Set to while the view is blending from transparent to black.
// VISIBLE | Set to when the overlay is visible but the user is not interacting with it.
// DRAGGING | Set to as soon as the user taps on the touch screen and while he is dragging.
// FALLING | Set to when the user releases the touch screen but did not swipe upwards to hide the overlay. Remains while the falling down animation is performed.
// HIDING | Set to when the user releases the touch screen and did swipe upwards to hide the overlay. Remains while the hiding animation is performed
// HIDDEN | Set to when the overlay is invisible to the user but still there.
// REMOVED --- Set to when the overlay view component was removed from screen. Remains while the overlay is hidden.
// From there it jumps back to "ADDED" as soon as the service gets an intent to show the overlay again.
// ADDED <---------------- Set to after the overlay view component was added to the screen.
// v |
// SHOWING | Set to while the view is blending from transparent to black.
// v |
// VISIBLE <-------- | Set to when the overlay is visible but the user is not interacting with it.
// v | |
// DRAGGING ---> FALLING | DRAGGING: Set to as soon as the user taps on the touch screen and while he is dragging.
// |-------- | FALLING: Set to when the user releases the touch screen but did not swipe upwards to hide the overlay. Remains while the falling down animation is performed.
// v | |
// HIDING | | Set to when the user releases the touch screen and did swipe upwards to hide the overlay. Remains while the hiding animation is performed.
// | | | This state is skipped, if the requested action is "HIDE_IMMEDIATELY" and hide_immediately() is called.
// v | |
// HIDDEN <---- | Set to when the overlay is invisible to the user but still there.
// v |
// REMOVED ---------------- Set to when the overlay view component was removed from screen. Remains while the overlay is hidden.
// From there it jumps back to "ADDED" as soon as the service gets an intent to show the overlay again.


@Override
Expand All @@ -79,9 +89,11 @@ protected void onServiceConnected() {
init();
// When the device does not support QuickTiles a custom notification is dropped
initializeNotification();
// Initialize broadcast receiver
initializeBroadcastReceiver();

// Set preference that the service is now running
writePref(true);
writeServiceRunningPref(true);
Log.i(getClass().getName(), "Accessibility service started.");
}

Expand All @@ -106,7 +118,15 @@ public int onStartCommand(Intent intent, int flags, int startId) {
// The requested action is to hide the overlay. Let's do it.
hide();
break;
case Constants.Intent.Extra.OverlayAction.HIDE_IMMEDIATELY:
Log.i(getClass().getName(), "Received intent to hide overlay (immediately)");

// The requested action is to hide the overlay immediately. Let's do it.
hide_immediately();
break;
case Constants.Intent.Extra.OverlayAction.NOTHING:
// You may say that this is useless. But wait and see...

Log.i(getClass().getName(), "Received intent to do nothing with the overlay");
break;
default:
Expand Down Expand Up @@ -276,6 +296,8 @@ private void removeView() {
windowManager.removeView(view);
// Set the state
state = Constants.Overlay.State.REMOVED;

writeOverlayShowingPref(false);
Log.i(getClass().getName(), "Successfully removed view");
} catch (IllegalArgumentException e) {
Log.e(getClass().getName(), "Failed to remove view");
Expand Down Expand Up @@ -315,6 +337,8 @@ public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
// When finished set the state to visible
state = Constants.Overlay.State.VISIBLE;
writeOverlayShowingPref(true);

Log.i(getClass().getName(), "Finished blending to black");
}
}).start();
Expand Down Expand Up @@ -404,6 +428,23 @@ public void onAnimationRepeat(Animator animation) {}
}
}

private void hide_immediately() {
// Check for the right state. The hiding action can be started while the overlay is only visible or
// while the user is dragging or while the overlay is falling back to its base position
if (state == Constants.Overlay.State.VISIBLE ||
state == Constants.Overlay.State.DRAGGING ||
state == Constants.Overlay.State.FALLING) {

// When finished set the state and remove the (invisible) view component
state = Constants.Overlay.State.HIDDEN;
removeView();

Log.i(getClass().getName(), "Successfully hidden overlay");
} else {
Log.e(getClass().getName(), "Overlay is not in required state. Cancel hiding. Overlay is in state " + Constants.Overlay.getStateName(state));
}
}

private void initializeNotification() {
// When the device does not support QuickTiles a custom notification is dropped.
// It gives users with older devices the ability to also start the overlay.
Expand All @@ -413,12 +454,28 @@ private void initializeNotification() {
}
}

private void writePref(boolean value) {
public void initializeBroadcastReceiver() {
if (this.phoneLockReceiver == null) this.phoneLockReceiver = new PhoneLockReceiver();
registerReceiver(this.phoneLockReceiver, new IntentFilter(Intent.ACTION_SCREEN_ON));
registerReceiver(this.phoneLockReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
}

public void unregisterBroadcastReceiver() {
unregisterReceiver(this.phoneLockReceiver);
unregisterReceiver(this.phoneLockReceiver);
}

private void writeServiceRunningPref(boolean value) {
running = value;
getSharedPreferences(Constants.Preferences.PREFERENCE_NAME, MODE_PRIVATE).edit().putBoolean(Constants.Preferences.IS_SERVICE_RUNNING, value).apply();
Log.i(getClass().getName(), "Successfully wrote preference " + Constants.Preferences.IS_SERVICE_RUNNING + " to " + (value ? "true":"false"));
}

private void writeOverlayShowingPref(boolean value) {
getSharedPreferences(Constants.Preferences.PREFERENCE_NAME, MODE_PRIVATE).edit().putBoolean(Constants.Preferences.IS_OVERLAY_SHOWING, value).apply();
Log.i(getClass().getName(), "Successfully wrote preference " + Constants.Preferences.IS_OVERLAY_SHOWING + " to " + (value ? "true":"false"));
}

private boolean getIsCloseOptionEnabled(String valueName) {
String[] defaults = getResources().getStringArray(R.array.close_options_values);

Expand All @@ -435,12 +492,15 @@ private boolean getIsCloseOptionEnabled(String valueName) {

@Override
public void onInterrupt() {
writePref(false);
writeServiceRunningPref(false);
// When the AccessibilityService is stopped for whatever reason try to hide the view
if (!hide()) {
// If the view cannot be hidden because for example it is in th wrong state just remove it
removeView();
}

unregisterBroadcastReceiver();

Log.i(getClass().getName(), "Accessibility service started.");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package android.jonas.fakestandby.service;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.jonas.fakestandby.utils.Constants;
import android.jonas.fakestandby.utils.Utils;
import android.os.PowerManager;
import android.util.Log;

public class PhoneLockReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
if (Utils.isOverlayShowing(context)) {
Intent new_intent = new Intent(context, AccessibilityOverlayService.class);
new_intent.putExtra(Constants.Intent.Extra.OverlayAction.KEY, Constants.Intent.Extra.OverlayAction.HIDE_IMMEDIATELY);
context.startService(new_intent);

Log.i(getClass().getName(), "Sent intent to hide overlay");

PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "fakestandby:overlaystopped");
wakeLock.acquire();
wakeLock.release();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ public class Constants {
public static final class Preferences {
public static final String IS_SERVICE_RUNNING = "is_accessibility_service_running_now"; // Key of the preference that stores weather the accessibility service is currently running
public static final String PREFERENCE_NAME = "default_preference"; // Name of the default preference to use.
public static final String FIRST_OPEN = "is_app_opened_for_first_time";
public static final String FIRST_OPEN = "is_app_opened_for_first_time"; // Key of the preference that stores weather the app is opened for the first time
public static final String IS_OVERLAY_SHOWING = "is_overlay_showing"; // Key of the preference that stores weather the overlay is currently active
}

public static final class Intent {
Expand All @@ -14,6 +15,7 @@ public static final class OverlayAction {
public static final String KEY = "overlay_action"; // The key for the extra of any intent that is used to control the overlay.
public static final byte SHOW = 1; // Value of the extra if one wants to show the overlay.
public static final byte HIDE = 0; // Value of the extra if one wants to hide the overlay.
public static final byte HIDE_IMMEDIATELY = 2; // Value of the extra if one wants to hide the overlay without blending.
public static final byte NOTHING = -1; // Value of the extra if nothing should happen. Just to have a default.
public static final byte DEFAULT = NOTHING;
}
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/java/android/jonas/fakestandby/utils/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,8 @@ public static boolean isFirstOpen(Context context) {
return firstOpen;
}

public static boolean isOverlayShowing(Context context) {
return context.getSharedPreferences(Constants.Preferences.PREFERENCE_NAME, Context.MODE_PRIVATE).getBoolean(Constants.Preferences.IS_OVERLAY_SHOWING, false);
}

}

0 comments on commit 081df2d

Please sign in to comment.