turn off the display even if the app is in background - android

I use the following code to create on the flight a window used as preview when a picture is taken:
void CreatePreviewDialog()
{
dummy_frame_layout = new DummyFrameLayout(context);
wm_params = new WindowManager.LayoutParams(
240, 320, 0, 0,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON|
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD|
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED|
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON|
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
PixelFormat.TRANSLUCENT);
wm_params.gravity = Gravity.CENTER;
wm_params.setTitle("Preview");
window_manager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
window_manager.addView(dummy_frame_layout, wm_params);
}
My app runs in background and it is waked-up by an alarm. It turns-on the display as you can see. As soon as the picture is taken, the window is destroyed using the following method:
void DestroyPreviewDialog()
{
((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).removeView(dummy_frame_layout);
dummy_frame_layout = null;
}
The problem is that the screen remains on. I would like to turn-off the screen when the preview window is closed. How does DestroyPreviewDialog() should be modified in such a way to turn-off the display? (of course the display should be turned off only if it was found turned off when CreatePreviewDialog() was called, but this is simple. For now I need a way to turn off the display)
EDIT
I've modified DestroyPreviewWindow() as follows:
private void DestroyPreviewDialog()
{
wm_params.screenBrightness = 0.0f;
window_manager.updateViewLayout(dummy_frame_layout, wm_params);
((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).removeView(dummy_frame_layout);
dummy_frame_layout = null;
}
but the results does not change. Screen remains on and bright!

Related

Android accessability highlight

I want to highlight all the accessability clickable objects on screen. For this i create an app with an always on top layout.
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics displaymetrics = new DisplayMetrics();
int screenWidth = displaymetrics.widthPixels;
int screenHeight = displaymetrics.heightPixels;
params = new WindowManager.LayoutParams(
720, 1280,
0, 0,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_FULLSCREEN,
PixelFormat.TRANSLUCENT);
mWindowManager.addView(testDrawView, params);
I also create an accessability service, in order to take all the accessability clickable elements box parameters. It works and the output is printed.
enter image description here
But the problem is that it doesnt update. When i do something on screen (all touches go through), i need the highlights of old elements to be deleted, and the higlight of new elements to be displayed. But changes do not update dynamycally, I need to open my app to force drawer to run.
I tried
class BrRec extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
mHeadLayer.rects.clear();
mHeadLayer.rects = (ArrayList<Rect>) intent.getSerializableExtra("rects");
for (int i = 0; i < mHeadLayer.rects.size(); ++i)
{
mHeadLayer.invalidate(mHeadLayer.rects.get(i));
}
mHeadLayer.invalidate();}}
But it doesnt work.
Is there a way to dynamically highlight screen objects? I want to redraw my always on top view, even when it is not active.
Maybe activate it somehow programatically?

Receive touch event on any screen

I'm trying to make a custom navigation button and have disabled the default navigation buttons provided by android by rooting my device. I want my custom navigation buttons to disappear after some interval of time (say 5 seconds). I have managed to do so. I want to make something such that whenever I touch anywhere on the screen, I can detect the touch event and show my navigation bar. Whether I'm on homescreen or any application, I can receive touch event. Is there a way to do so or do I need to go android source code?
Thank you
OnCreate of your Service: used WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH flag.
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(getBaseContext(),"onCreate", Toast.LENGTH_LONG).show();
mView = new HUDView(this);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.RIGHT | Gravity.TOP;
params.setTitle("Load Average");
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(mView, params);
}
Now, you will start getting each and every click event.
see this Creating a system overlay window (always on top)

Why is hardware acceleration not working on my View?

I'm using Facebook's Rebound library to replicate the bouncy animations seen in their chat heads implementation. The problem is, most of the time the animation stutters. A few pictures will explain this better. Here's the buttery-smooth chat heads animation:
And here's my attempt (notice how the animation for the white View skips nearly all frames):
Once in a while it works smoothly:
Below is the code I'm using currently (the entire project is up on Github if you want to set it up quickly). I'm guessing this has something to do with hardware acceleration not being enabled correctly on my View. There are 2 Springs in my SpringSystem, one for the "bubble" (the Android icon) and another for the content (the white View that is displayed on tapping the bubble). Any help on how to solve this issue would be greatly appreciated. Thanks.
AndroidManifest.xml:
<application android:hardwareAccelerated="true" ...>
...
</application>
AppService.java:
// the following code is in AppService#onCreate()
// AppService extends android.app.Service
// full code at https://github.com/vickychijwani/BubbleNote
mContent.setLayerType(View.LAYER_TYPE_HARDWARE, null);
final Spring bubbleSpring = system.createSpring();
bubbleSpring.setCurrentValue(1.0);
bubbleSpring.addListener(new SpringListener() {
#Override
public void onSpringUpdate(Spring spring) {
float value = (float) spring.getCurrentValue();
params.x = (int) (mPos[0] * value);
params.y = (int) (mPos[1] * value);
mWindowManager.updateViewLayout(mBubble, params);
// fire the second animation when this one is about to end
if (spring.isOvershooting() && contentSpring.isAtRest()) {
contentSpring.setEndValue(1.0);
}
}
// ...
});
final Spring contentSpring = system.createSpring();
contentSpring.setCurrentValue(0.0);
contentSpring.addListener(new SpringListener() {
#Override
public void onSpringUpdate(Spring spring) {
// always prints false?!
Log.d(TAG, "hardware acc = " + mContent.isHardwareAccelerated());
float value = (float) spring.getCurrentValue();
// clamping is required to prevent flicker
float clampedValue = Math.min(Math.max(value, 0.0f), 1.0f);
mContent.setScaleX(value);
mContent.setScaleY(value);
mContent.setAlpha(clampedValue);
}
// ...
});
I've figured it out by going through the framework source code.
TL;DR: add WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED to the layout flags when you manually attach a View to a Window / WindowManager; setting android:hardwareAccelerated=true in the manifest won't work.
I'm manually attaching my View to the WindowManager (because I need to create my UI in a Service to emulate chat heads) like so:
// code at https://github.com/vickychijwani/BubbleNote/blob/eb708e3910a7279c5490f614a7150009b59bad0b/app/src/main/java/io/github/vickychijwani/bubblenote/BubbleNoteService.java#L54
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
mBubble = (LinearLayout) inflater.inflate(R.layout.bubble, null, false);
// ...
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
// ...
mWindowManager.addView(mBubble, params);
Let's go digging...
Welcome to the Android framework
I started debugging at View#draw(...), then went up the call stack to ViewRootImpl#draw(boolean). Here I came across this piece of code:
if (!dirty.isEmpty() || mIsAnimating) {
if (attachInfo.mHardwareRenderer != null && attachInfo.mHardwareRenderer.isEnabled()) {
// Draw with hardware renderer.
mIsAnimating = false;
mHardwareYOffset = yoff;
mResizeAlpha = resizeAlpha;
mCurrentDirty.set(dirty);
dirty.setEmpty();
attachInfo.mHardwareRenderer.draw(mView, attachInfo, this,
animating ? null : mCurrentDirty);
} else {
// If we get here with a disabled & requested hardware renderer, something went
// wrong (an invalidate posted right before we destroyed the hardware surface
// for instance) so we should just bail out. Locking the surface with software
// rendering at this point would lock it forever and prevent hardware renderer
// from doing its job when it comes back.
// Before we request a new frame we must however attempt to reinitiliaze the
// hardware renderer if it's in requested state. This would happen after an
// eglTerminate() for instance.
if (attachInfo.mHardwareRenderer != null &&
!attachInfo.mHardwareRenderer.isEnabled() &&
attachInfo.mHardwareRenderer.isRequested()) {
try {
attachInfo.mHardwareRenderer.initializeIfNeeded(mWidth, mHeight,
mHolder.getSurface());
} catch (OutOfResourcesException e) {
handleOutOfResourcesException(e);
return;
}
mFullRedrawNeeded = true;
scheduleTraversals();
return;
}
if (!drawSoftware(surface, attachInfo, yoff, scalingRequired, dirty)) {
return;
}
}
}
In my case ViewRootImpl#drawSoftware() was being called, which uses the software renderer. Hmm... that means the HardwareRenderer is null. So I went searching for the point of construction of the HardwareRenderer, which is in ViewRootImpl#enableHardwareAcceleration(WindowManager.LayoutParams):
// Try to enable hardware acceleration if requested
final boolean hardwareAccelerated =
(attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
if (hardwareAccelerated) {
// ...
mAttachInfo.mHardwareRenderer = HardwareRenderer.createGlRenderer(2, translucent);
// ...
}
Aha! There's our culprit!
Back to the problem at hand
In this case Android does not automatically set FLAG_HARDWARE_ACCELERATED for this Window, even though I've set android:hardwareAccerelated=true in the manifest. So the fix is simply:
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
mBubble = (LinearLayout) inflater.inflate(R.layout.bubble, null, false);
// ...
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE,
// NOTE
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
// ...
mWindowManager.addView(mBubble, params);
Although the animation is still not as smooth as Facebook's. I wonder why... (before anyone asks: no, there are no copious logs during the animation; and yes, I've tried with a release build)

Android 4.4 hide navbar/statusbar using Accessibility service & service

I have implemented some features by integrating accessibility service for my application.
I currently have a 'system overlay' ImageView that can detect TouchEvent's. however i have seen it done that immersive mode, hiding the statusbar or navbar is possible without root.
i need to beable to access the view of my touch detection window in order to process any accessibility
My Accessibility service contains:
...
#Override
public void onServiceConnected() {
serviceInstance = this;
}
...
my touch detector:
...
WindowManager wm;
private MyAccessibilityService myAccessibilityService;
private ImageView mTouchDetector;
#Override
public void onCreate() {
super.onCreate();
myAccessibilityService = MyAccessibilityService.getSharedInstance();
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
100,
100,
0, 0,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, debugMode());
params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(mTouchDetector, params);
}
...
I have partially solved this problem, however having some trouble with the back button, check here to see if it gets resolved.
create the service as normal but add these flags to the overlay:
to the window manager:
TYPE_PRIORITY_PHONE, FLAG_FULLSCREEN |
FLAG_NOT_TOUCH_MODAL
to the view:
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
FloatingView.setSystemUiVisibility(uiOptions);
Android floating window with hidden statusbar Accessibility problems

I want to create a button located on the top of all activities dynamically

I created it in DialpadFragment, but when the MO call was making, the InCallScreen would always overlay my button. Here is my code:
private void createStopButton() {
if (mstopButton == null) {
mstopButton = new Button(mActivity);
mstopButton.setText("Stop Dial");
}
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY|
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
PixelFormat.OPAQUE);
params.gravity = Gravity.CENTER | Gravity.TOP;
final WindowManager wm = (WindowManager)mActivity.getSystemService(Context.WINDOW_SERVICE);
mstopButton.setOnClickListener( new View.OnClickListener() {
public void onClick(View view) {
mIsRedialStatus = false;
wm.removeView(mstopButton);
}
});
wm.addView(mstopButton, params);
}
Anybody can help fix how to bring my button up the top of the screen. I have investigated lots of code in internet, I found that they put the top layer related code in a service.
Should I also implement it with a service? Thanks very much!
I just answered one similar to this. Check out the the first part of this answer: Creating bodyless activity
But yes, you'll need to do this via a service. Just remember you'll need to find a way to start the service (easiest way is to use an activity).

Categories

Resources