Skip to content

Instantly share code, notes, and snippets.

@Bringoff
Last active February 14, 2019 09:30
Show Gist options
  • Select an option

  • Save Bringoff/33e53b190f6e1b3d5319bf26b92ad5d5 to your computer and use it in GitHub Desktop.

Select an option

Save Bringoff/33e53b190f6e1b3d5319bf26b92ad5d5 to your computer and use it in GitHub Desktop.
Overlay drawing permission is activated on separate screen. But after activation that permission some users can't figure out how to return to the original app. Good approach is to open the app automatically after activation. The problem is we cannot listen to overlay permission changes. So here is workaround.
/**
* Looks like there is no adequate way to listen to this permission change, so do workaround here.
* Normally, we check the permission every 0.5 second. But on Oreo this won't work as Settings.canDrawOverlays still
* returns false after activation but before returning to the app (bug https://issuetracker.google.com/issues/66072795).
* Use OnOpChangedListener on Oreo.
*/
public class DrawOverPermissionActivationListener implements LifecycleObserver {
private AppCompatActivity activity;
private final OverlayManager overlayManager;
private final Class activityToBringToFrontOnDetection;
private AppOpsManager appOpsManager;
private Disposable listenOverlayPermission;
private AppOpsManager.OnOpChangedListener onOpChangedListener = null;
private boolean canDrawOverlaysOreo = false;
public DrawOverPermissionActivationListener(AppCompatActivity activity, OverlayManager overlayManager,
Class activityToBringToFrontOnDetection) {
this.activity = activity;
this.appOpsManager = (AppOpsManager) activity.getSystemService(Context.APP_OPS_SERVICE);
activity.getLifecycle().addObserver(this);
this.overlayManager = overlayManager;
this.activityToBringToFrontOnDetection = activityToBringToFrontOnDetection;
}
public void listen() {
if (isCanDrawOverlaysReliable()) {
listenOverlayPermission = Observable.interval(500L, TimeUnit.MILLISECONDS)
.timeInterval()
.compose(RxUtils.applyObservableSchedulers())
.subscribe(longTimed -> {
if (overlayManager.canDrawOverlays()) {
bringToFront();
listenOverlayPermission.dispose();
}
});
} else {
onOpChangedListener = (op, calledPackageName) -> {
String myPackageName = activity.getPackageName();
if (myPackageName.equals(calledPackageName) &&
AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW.equals(op)) {
canDrawOverlaysOreo = !canDrawOverlaysOreo;
if (canDrawOverlaysOreo) {
bringToFront();
appOpsManager.stopWatchingMode(onOpChangedListener);
onOpChangedListener = null;
}
}
};
appOpsManager.startWatchingMode(AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW,
null, onOpChangedListener);
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
public void onListenerActivityDestroyed() {
if (listenOverlayPermission != null && !listenOverlayPermission.isDisposed()) {
listenOverlayPermission.dispose();
} else if (onOpChangedListener != null) {
appOpsManager.stopWatchingMode(onOpChangedListener);
}
activity = null;
listenOverlayPermission = null;
}
private boolean isCanDrawOverlaysReliable() {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.O || Build.VERSION.SDK_INT >= Build.VERSION_CODES.P;
}
private void bringToFront() {
Intent intent = new Intent(activity, activityToBringToFrontOnDetection);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
activity.startActivity(intent);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment