I got a problem when I tried to close the notification bar from my application.
here is where i try to close it
#Override
public void onWindowFocusChanged(boolean hasFocus)
{
Log.i("FocusChanged", "Focus changed");
if(!hasFocus)
{
Log.e("Focus debug", "Lost focus !");
// Close every kind of system dialog
Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
getApplicationContext().sendBroadcast(closeDialog);
Log.i("FocusChanged", "Focus changed - iam supposed to close this dialogs");
}
super.onWindowFocusChanged(hasFocus);
}
But it don't work.
Unless if I add a breakpoint to the function.
Everytime that i open the system notification i got the log that say "Focus changed" so my app run the code, but hasFocus not set to true, or as I said only if i ran the debugger and set breakpoint in the function.
We could not prevent the status appearing in full screen mode in kitkat devices, so made a hack which still suits the requirement ie block the status bar from expanding.
For that to work, the app was not made full screen. We put a overlay over status bar and consumed all input events. It prevented the status from expanding.
note:
customViewGroup is custom class which extends any layout(frame,relative layout etc) and consumes touch event.
to consume touch event override the onInterceptTouchEvent method of the view group and return true
You also need to set the android permission
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
You need an extended ViewGroup class to handle Touch Event
public class customViewGroup extends ViewGroup {
public customViewGroup(Context context) {
super(context);
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.v("customViewGroup", "**********Intercepted");
return true;
}
}
in the activity where you want to disable the notification bar you need to add this function (don't forget to add field variable CustomViewGroup blockingView)
private void disableNotificationBar(){
WindowManager manager = ((WindowManager) getApplicationContext()
.getSystemService(Context.WINDOW_SERVICE));
WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams();
localLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
localLayoutParams.gravity = Gravity.TOP;
localLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
// this is to enable the notification to recieve touch events
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
// Draws over status bar
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
localLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
localLayoutParams.height = (int) (50 * getResources()
.getDisplayMetrics().scaledDensity);
localLayoutParams.format = PixelFormat.TRANSPARENT;
blockingView = new CustomViewGroup(this);
manager.addView(blockingView, localLayoutParams);
}
and then in you onCreate you need to call
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
....
disableNotificationBar();
}
You need to remove it on the onDestroy() to be able to close your application
#Override
protected void onDestroy() {
super.onDestroy();
if (blockingView!=null) {
WindowManager manager = ((WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE));
manager.removeView(blockingView);
}
}
You also need to adjust the overlay size, according to previous answer 40 is enought, but you don't want to prevent user from doing action on your own app, if overlay is to height it will intercept event on your Activity too.
Also in android version > to 5.1 you need an extra permission from the user, add this on your onCreate function insted of the function call
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(this)) {
Toast.makeText(this, "Please give my app this permission!", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE);
} else {
disableNotificationBar();
}
}
else {
disableNotificationBar();
}
Related
I am working on an android application where I use a custom view to my window. I have the following code to do it :-
private void systemOverlayFullScreen()
{
WindowManager manager = ((WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE));
//manager.removeView(view);
WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams();
// changed to alerts or overlay from system_error
localLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
// set width and height of overlay originally -1
localLayoutParams.width = -1;
// changed gravity to bottom so as to hide the stop the home button press; originally -1
localLayoutParams.height = -1;
localLayoutParams.y = -getNavigationBarHeight();
localLayoutParams.x = 0;
localLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
// this is to enable the notification to recieve touch events
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
// Draws over status bar
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
// you can change it to transparent
//localLayoutParams.format = PixelFormat.TRANSLUCENT;
localLayoutParams.alpha = 0.3f;
CustomViewGroup view = new CustomViewGroup(this);
manager.addView(view, localLayoutParams);
}
When I click the home button and then relaunch my app again, the previously added custom view is still present. I want to remove it when the app relaunches.
I have tried doing :-
#Override
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
if(view.getWindowToken() != null)
{
Toast.makeText(getApplicationContext(), "View present", Toast.LENGTH_SHORT).show();
WindowManager manager = ((WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE));
manager.removeView(view);
}
else
{
Toast.makeText(getApplicationContext(), "View not present", Toast.LENGTH_SHORT).show();
}
}
But this doesnot work.
Can anyone tell me how to remove a view dynamically when the app starts ?
Your code will execute exactly as specified when you open the app everytime. Meaning it will add the CustomView once the app is opened. The onRestart method takes into account the activity restart not the whole app. You could perform a check before adding the view. i.e the user enters there name and you store it SharedPreferences. Then you can test if the user signed up and if they did it means when theres a restart the CustomView won't be added to your window.
I'm using following code for hiding status bar with full screen purpose:
void HideEverything(){
if (Build.VERSION.SDK_INT < 16) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
} else {
View decorView = getWindow().getDecorView();
// Hide the status bar.
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);
// Remember that you should never show the action bar if the
// status bar is hidden, so hide that too if necessary.
ActionBar actionBar = getActionBar();
actionBar.hide();
}
}
It shows Screen in full-screen mode but when I touch status bar it shows status bar.
I tried other options to add the full screen and no title bar theme in application and activity level in manifest, but still results are the same... :(
I don't want to show status bar at any step.
How to achieve this in android?
Edit :
Android OS version is 4.4.2
(Above code is working on 4.3 but not on 4.4.2)
Update:
Problem has been solved...
Answer is written below separately...
No solution could work for the problem as Android version is 4.4.2.
As commented by #Academy of Programmer; this solution does not work on Android 6 and above.
But as per the suggestion by Sunny, problem has been solved by preventing the expansion of status bar.
Solution is:
Write an inline customViewGroup class in your main activity.
public class customViewGroup extends ViewGroup {
public customViewGroup(Context context) {
super(context);
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.v("customViewGroup", "**********Intercepted");
return true;
}
}
Now in your onCreate method of mainActivity add following code before setContentView() :
WindowManager manager = ((WindowManager) getApplicationContext()
.getSystemService(Context.WINDOW_SERVICE));
WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams();
localLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
localLayoutParams.gravity = Gravity.TOP;
localLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
// this is to enable the notification to receive touch events
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
// Draws over status bar
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
localLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
localLayoutParams.height = (int) (50 * getResources()
.getDisplayMetrics().scaledDensity);
localLayoutParams.format = PixelFormat.TRANSPARENT;
customViewGroup view = new customViewGroup(this);
manager.addView(view, localLayoutParams);
Above code will disable the expansion of status bar.
Now make full screen by following code, add it just below the above code and before the setContentView :
//fullscreen
requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
Now in manifest add the permission:
<!-- prevent expanding status bar -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
and you are done.... :)
drawback : This code disables expansion of status bar for the device not just for an activity or an application, so use it if you really need it.
Thank you for all the solutions and suggestions... :)
We cannot prevent the status appearing in full screen mode in kitkat or above devices, so try a hack to block the status bar from expanding.
For an idea, put an overlay over status bar and consume all input events. It will prevent the status bar from expanding.
Using below code you can use full screen ;
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
Write below code above setcontentview.
Note : Don't give any theme to this activity.
Hope this helps.
use following code onCreate
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
I'm created WindowPopup, with edittext. And when i focused on it, soft keyboard show and displace this popup above the top bounds, so i can't see what i'm typing. I want to show keyboard without any displace of views, just above them.
I read that i can change softInputMode for it, so i'm created class which extends from EditText, and tried to change inputMode in onFocusListener, but it didn't help.
setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View veiw, boolean has_focus) {
if (has_focus) {
//Try to change input mode to prevent displacing
((Activity) getContext()).getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
} else {
//.. return back previous input mode
}
});
I did so, because i need such behavior only in this popup, but i even try to change action attribute in my manifets file
android:windowSoftInputMode="adjustNothing"
or
android:windowSoftInputMode="stateHidden"
Can i show keyboard without any displacing of view?
P.S. i'm using Android API 15
When PopupWindow creates popup view, it sets to it new WindowManager.LayoutParams with softInputMode, which is overwrites behavior of Window.softInputMode. Here piece of code from PopupWindow
private WindowManager.LayoutParams createPopupLayout(IBinder token) {
WindowManager.LayoutParams p = new WindowManager.LayoutParams();
p.gravity = Gravity.LEFT | Gravity.TOP;
p.width = mLastWidth = mWidth;
p.height = mLastHeight = mHeight;
if (mBackground != null) {
p.format = mBackground.getOpacity();
} else {
p.format = PixelFormat.TRANSLUCENT;
}
p.flags = computeFlags(p.flags);
p.type = mWindowLayoutType;
p.token = token;
/*mSoftInputMode is the private field which is by default equals
to WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
*/
p.softInputMode = mSoftInputMode;
}
So to change softInputMode you need just to call public method of PopupWindow
setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
And there is no need to remember previous soft input method, because this behavior will be only for this PopupWindow
When I create an activity using the fullscreen activity wizard it creatre a fullscreen activity but whenever I click anywhere on the screen the actionbar shows for a few seconds. How can I stop it from doing so?
Full code of FullScreenActivity.java
/**
* An example full-screen activity that shows and hides the system UI (i.e.
* status bar and navigation/system bar) with user interaction.
*
* #see SystemUiHider
*/
public class FullscreenActivity extends Activity {
/**
* Whether or not the system UI should be auto-hidden after
* {#link #AUTO_HIDE_DELAY_MILLIS} milliseconds.
*/
private static final boolean AUTO_HIDE = true;
/**
* If {#link #AUTO_HIDE} is set, the number of milliseconds to wait after
* user interaction before hiding the system UI.
*/
private static final int AUTO_HIDE_DELAY_MILLIS = 3000;
/**
* If set, will toggle the system UI visibility upon interaction. Otherwise,
* will show the system UI visibility upon interaction.
*/
private static final boolean TOGGLE_ON_CLICK = true;
/**
* The flags to pass to {#link SystemUiHider#getInstance}.
*/
private static final int HIDER_FLAGS = SystemUiHider.FLAG_HIDE_NAVIGATION;
/**
* The instance of the {#link SystemUiHider} for this activity.
*/
private SystemUiHider mSystemUiHider;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fullscreen);
final View controlsView = findViewById(R.id.fullscreen_content_controls);
final View contentView = findViewById(R.id.fullscreen_content);
// Set up an instance of SystemUiHider to control the system UI for
// this activity.
mSystemUiHider = SystemUiHider.getInstance(this, contentView,
HIDER_FLAGS);
mSystemUiHider.setup();
mSystemUiHider
.setOnVisibilityChangeListener(new SystemUiHider.OnVisibilityChangeListener() {
// Cached values.
int mControlsHeight;
int mShortAnimTime;
#Override
#TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
public void onVisibilityChange(boolean visible) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
// If the ViewPropertyAnimator API is available
// (Honeycomb MR2 and later), use it to animate the
// in-layout UI controls at the bottom of the
// screen.
if (mControlsHeight == 0) {
mControlsHeight = controlsView.getHeight();
}
if (mShortAnimTime == 0) {
mShortAnimTime = getResources().getInteger(
android.R.integer.config_shortAnimTime);
}
controlsView
.animate()
.translationY(visible ? 0 : mControlsHeight)
.setDuration(mShortAnimTime);
} else {
// If the ViewPropertyAnimator APIs aren't
// available, simply show or hide the in-layout UI
// controls.
controlsView.setVisibility(visible ? View.VISIBLE
: View.GONE);
}
if (visible && AUTO_HIDE) {
// Schedule a hide().
delayedHide(AUTO_HIDE_DELAY_MILLIS);
}
}
});
// Set up the user interaction to manually show or hide the system UI.
contentView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (TOGGLE_ON_CLICK) {
mSystemUiHider.toggle();
} else {
mSystemUiHider.show();
}
}
});
// Upon interacting with UI controls, delay any scheduled hide()
// operations to prevent the jarring behavior of controls going away
// while interacting with the UI.
findViewById(R.id.dummy_button).setOnTouchListener(
mDelayHideTouchListener);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Trigger the initial hide() shortly after the activity has been
// created, to briefly hint to the user that UI controls
// are available.
delayedHide(100);
}
/**
* Touch listener to use for in-layout UI controls to delay hiding the
* system UI. This is to prevent the jarring behavior of controls going away
* while interacting with activity UI.
*/
View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (AUTO_HIDE) {
delayedHide(AUTO_HIDE_DELAY_MILLIS);
}
return false;
}
};
Handler mHideHandler = new Handler();
Runnable mHideRunnable = new Runnable() {
#Override
public void run() {
mSystemUiHider.hide();
}
};
/**
* Schedules a call to hide() in [delay] milliseconds, canceling any
* previously scheduled calls.
*/
private void delayedHide(int delayMillis) {
mHideHandler.removeCallbacks(mHideRunnable);
mHideHandler.postDelayed(mHideRunnable, delayMillis);
}
}
if i understand correctly, you just want to hide the action bar?
if yes, Change this line (changing the flag_hide_navigation to 0).
private static final int HIDER_FLAGS = 0;// SystemUiHider.FLAG_HIDE_NAVIGATION;
and add this to the onCreate call:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_ACTION_BAR); //new
getActionBar().hide(); //new
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_fullscreen);
afterwards, if you want to show the action bar, just call from anywhere in the activity :
getActionBar().show();
I Tried The Same By Putting 0 in place of 3000
private static final int AUTO_HIDE_DELAY_MILLIS = 3000;
But its becoming too laggy...
So,The trick u to make changes in androidmanifest.xml
add
android:theme="#android:style/Theme.NoTitleBar.Fullscreen"
to AndroidManifest.xml underApplication
This worked for me. Although the navigator isn't removed completely it doesn't allow much time for the user to interact, plus the button icons are small dots. Also this cuts down on the amount of code needed all over the place to make a screen fullscreen.
SystemUiHider hider = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//go full screen with no title
this.requestWindowFeature(Window.FEATURE_PROGRESS); //show progress on loadup
this.requestWindowFeature(Window.FEATURE_NO_TITLE); //hide the title bar
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); //go fullscreen
setContentView(R.layout.activity_main);
//hide the navigation controls
final RelativeLayout mainLayout = (RelativeLayout)this.findViewById(R.id.mainLayout);
hider = SystemUiHider.getInstance(this, mainLayout, SystemUiHider.FLAG_HIDE_NAVIGATION);
hider.setup();
hider.setOnVisibilityChangeListener(new SystemUiHider.OnVisibilityChangeListener() {
#Override
#TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
public void onVisibilityChange(boolean visible) {
if (visible) {
//will make navigator into small dots
hider.hide();
//must use delayed to force navigator to disappear completely
final Handler mHideHandler = new Handler();
final Runnable mHideRunnable = new Runnable() {
#Override
public void run() {
hider.hide();
}
};
mHideHandler.removeCallbacks(mHideRunnable);
mHideHandler.postDelayed(mHideRunnable, 1000); //min 1 sec to work
}
}
});
hider.hide();
//do the rest of your onCreate stuff here
}
I took a deep look into the code and started the activity on an Android 4.2 device without physical navigation buttons. The default configuration is as fullscreen as possible. It hides status bar, action bar and navigation bar. So how would the user be supposed to get out of your activity if not with a click anywhere on the screen? Anything else would be very restricting and bad usability. I think this is the reason why this behavior can not be manipulated.
What you can do instead, is change the SystemUiHider so that it hides the status bar and the action bar, but not the navigation bar. It instead dimmes the navigation bar to three pale dots, see the screenshot below.
There must be a better way to achieve this, but the following works. Comment these lines in the end of the SystemUiHiderHoneycomb() constructor:
if ((mFlags & FLAG_HIDE_NAVIGATION) != 0) {
// If the client requested hiding navigation, add relevant flags.
mShowFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
mHideFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
mTestFlags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
}
The activity then stays fullscreen on user interaction and you can toggle() it at a particular event. Of course, you would still have to do the change from my original answer to disable the click behavior.
Original answer:
I guess you have to comment this part:
// Set up the user interaction to manually show or hide the system UI.
contentView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (TOGGLE_ON_CLICK) {
mSystemUiHider.toggle();
} else {
mSystemUiHider.show();
}
}
});
In api19 we can use:
getWindow().getDecorView()
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
to hide navigation bar along with status bar
Change the theme of your activity to not have action bar. Best is to inherit from action bar Sherlock activity and remove the action bar
Though its too late to post an answer, but as far as I can understand the question and since I am working using the Full Screen Activity template provided in Android Studio, I think the answer to this question is to disable action bar which becomes visible when the user interacts with the UI, which can be achieved just by disabling the OnClickListener on contentView
i.e.
contentView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (TOGGLE_ON_CLICK) {
mSystemUiHider.toggle();
} else {
mSystemUiHider.show();
}
}
});
i.e. comment out the onClick method implementation.
Just comment out
if (TOGGLE_ON_CLICK) {
mSystemUiHider.toggle();
} else {
mSystemUiHider.show();
}
By default the state is Off. Toggle happens because there is a onclick listener also added which toggles the screen.
You could simply not add it and delete the code snippet.
The newest code is
// Set up the user interaction to manually show or hide the system UI.
mContentView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// toggle();
}
I simply commented out toggle() and voila
Is there anyway to prevent users from sliding the status bar (expand) or collapsing back?
I'm trying out a lockscreen replacement and seems like it's a must-have feature. Is there any possible way to do it without requiring root privileges?
You can actually prevent the status bar from expanding, without rooting phone. See this link. This draws a window the height of the status bar and consumes all touch events.
Call the following code just after onCreate().
public static void preventStatusBarExpansion(Context context) {
WindowManager manager = ((WindowManager) context.getApplicationContext()
.getSystemService(Context.WINDOW_SERVICE));
Activity activity = (Activity)context;
WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams();
localLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
localLayoutParams.gravity = Gravity.TOP;
localLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
// this is to enable the notification to recieve touch events
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
// Draws over status bar
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
localLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
//https://stackoverflow.com/questions/1016896/get-screen-dimensions-in-pixels
int resId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
int result = 0;
if (resId > 0) {
result = activity.getResources().getDimensionPixelSize(resId);
}
localLayoutParams.height = result;
localLayoutParams.format = PixelFormat.TRANSPARENT;
customViewGroup view = new customViewGroup(context);
manager.addView(view, localLayoutParams);
}
public static class customViewGroup extends ViewGroup {
public customViewGroup(Context context) {
super(context);
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.v("customViewGroup", "**********Intercepted");
return true;
}
}
Short answer: this is impossible!
Now should you be interested to know why this is impossible:
There are two permissions for manipulating the system status bar, EXPAND_STATUS_BAR and STATUS_BAR. The former can be requested by any application, but the later is reserved for applications signed with the platform signature (system applications, not third-party). It is possible to expand/ collapse the system status bar (see "How to open or expand status bar through intent?") but note that reflection is required because the StatusBarManager class is not part of the SDK. The disable method, which is used by the Android dialer to prevent the status bar from being expanded, cannot be accessed by an application without the aforementioned STATUS_BAR permission.
Sources: personal experience :-)
First of all, it's impossible to modify the Status Bar if your app is not signed with the phone's rom certified, if you try to modify it you'll get an Security Exception.
Update: In new APIs the method is "collapsePanels" instead of "collapse".
The only way I've found after several hours of work is by overriding the "onWindowFocusChanged" method of the activity and when it loses the focus (maybe the user has touched the notifications bar), force to collapse the StatusBar, here is the code (working on a Defy+ 2.3.5).
You need to declare the following permission on the manifest:
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR"/>
And override the following method:
public void onWindowFocusChanged(boolean hasFocus)
{
try
{
if(!hasFocus)
{
Object service = getSystemService("statusbar");
Class<?> statusbarManager = Class.forName("android.app.StatusBarManager");
Method collapse = statusbarManager.getMethod(Build.VERSION.SDK_INT > 16 ? "collapsePanels" : "collapse");
collapse.setAccessible(true);
collapse.invoke(service);
}
}
catch(Exception ex)
{
}
}
Update: You will have to use your own custom Alert Dialog by overriding it their onWindowFocusChanged method too, because Alert Dialogs have their own focus.
This actually can be done via a little hack that I accidentally discovered, but requires the permission android.permission.SYSTEM_ALERT_WINDOW:
What you do is add a view the exact size of the status bar directly to the WindowManager with the certain parameters that covers the status bar and prevents it from receiving touch events:
View disableStatusBarView = new View(context);
WindowManager.LayoutParams handleParams = new WindowManager.LayoutParams(
WindowManager.LayoutParams.FILL_PARENT,
<height of the status bar>,
// This allows the view to be displayed over the status bar
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
// this is to keep button presses going to the background window
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
// this is to enable the notification to recieve touch events
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
// Draws over status bar
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.TRANSLUCENT);
handleParams.gravity = Gravity.TOP;
context.getWindow().addView(disableStatusBarView, handleParams);
This will basically create a transparent view over the status bar that will receive all the touch events and block the events from reaching the status bar and therefore prevents it from being expanded.
NOTE: This code is untested, but the concept works.
I tried the solutions mentioned by GrantLand and PoOk but both didn't work in my case. Though, Another solution Clear/Hide Recent Tasks List did the trick for me. I am writing a launcher app for which I had to disable a recent applications menu so user cannot open a locked app from it. Also, I had to prevent against notification bar expansion and this trick made me achieve both. Override OnWindowFocusChanged method in your activity and check if this is what u wanted.
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
Log.d("Focus debug", "Focus changed !");
if(!hasFocus) {
Log.d("Focus debug", "Lost focus !");
Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
sendBroadcast(closeDialog);
}
}
For a lockscreen Why don't you just use the following in your main activity:
#Override
public void onAttachedToWindow() {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
}
If the user doesn't have a secure lockscreen set the app will let the user pull the status bar down and open activities but that doesn't matter as the user obviously doesn't want a secure screen anyway.
If the user does have a secure locksreen set then the app will show the status bar but will not allow interactions with it. This is because the phone is still actually locked and only your activity is allowed to operate until the user unlocks the phone. Also closing your app in anyway will open the standard secure lockscreen. All this is highly desirable because you don't have to spend all that time coding secure features that you can't guarantee will be as secure as the stock ones.
If you really don't want the user to be able to interact with the status bar, maybe you can leave out the flag FLAG_DISMISS_KEYGUARD call. Then just before you are about to unlock the phone set the flag like I showed in the first block. I don't know if this last part works but it's worth a try.
Hope that helps
Sorry but it does not work. using FLAG_LAYOUT_IN_SCREEN prevents you from catching any touch events.
And BTW:
to add a view to the window use the window manager:
WindowManager winMgr = (WindowManager)getSystemService(WINDOW_SERVICE);
winMgr.addView(disableStatusBar, handleParams);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);