When system enters into TouchMode, I'd like to know which widget will lose focus. When system quits TouchMode, I'd also like to know which widget will get focus. Overriding onFocusChange() didn't satisfy me, since it couldn't tell TouchMode change, since it could happen in every mode, touch, trackball, key navigation, etc.
SDK said only one API View.isInTouchMode() there it is. So, is it possible to detect TouchMode change?
Long shot but you probably need to maintain states manually. So you keep a a flag , lets say isTouchMode which you can set every time any of the widgets are touched and unset when something gets focus.
Use ViewTreeObserver.addOnTouchModeChangeListener(). It will tell you when the mode changes.
http://developer.android.com/reference/android/view/ViewTreeObserver.html
Related
Background
There are some nice apps out there that show some layout on top , while the user is making a call or answering one (like "current caller id").
I need to create an app with the ability to show something on top , during a call, and allow it to be interactive.
The problem
Using broadcastReceiver ,foreground service and SYSTEM_ALERT permission, I've succeeded showing something on the screen during calls.
As long as the content being shown is static, I have no problems.
However, I've noticed that when I try to make the content being shown to be interactive , I face some problems:
Everything is jumpy and this includes not only animations, but also setting visibility to visible/gone. I hate to think how it would work like when I need to make things draggable.
Not sure if this is the reason, but using the SlidingDrawer make the entire width belong to the SlidingDrawer and you cannot click through it. This means that if its location is at the bottom, you can't touch the "answer" button when someone calls you.
The question
What is the reason for those problems?
How can I fix them and be able to show things right?
How do other apps handle it right ?
EDIT: about the SlidingDrawer , it seems that it has terrible bugs about its location and size, and the content area, even when it's not shown to the user and the user can see through, it cannot be touched through. Still, I don't know why, and how to fix it, and I also don't know why things are so jumpy compared to normal apps (probably because of over-drawing, but it's really really slow).
Maybe this question should be more general: how to make a floating window like on AirCalc, that can be moved easily yet still be quite fast.
For the dragging functionality, I've tried to get the layoutParams of the root view (which is of type WindowManager.LayoutParams ) that I show, update it and set it again, but for some reason it didn't do anything. Wonder what I'm doing wrong.
EDIT: it seems that i should be using windowManager.updateViewLayout for updating the layoutParams. Using this post , I've made it perfectly draggable.
Ok, I've come up to some conclusions about this, first to answer my original questions:
it's probably because of overdraw and the views i've used. I wanted to try out libraries that could replace the slidingDrawer , but each had a different problem. using simple views proved that the idea in general works.
in the case of visibility changes, it was jumpy because the size of the view wasn't able to fit using the current WindowManager.LayoutParams size.
slidingDrawaer does have issues since it uses the whole size it get when closed or opened.
now to the rest of the issues :
unable to drag ? instead of the regular setLayoutParams , use windowManager.updateViewLayout .
unable to touch outside of the view ? set its minimal size according to your needs. you can also set the window flags so that touch event would go through .
want to listen to calls events ? you can use the broadcastReceiver for triggering the showing of the app, but I suspect that hanging the call might cause the intent be received later sometimes. I think you can use telephonyManager and listen to events there, using the service you run in the foreground (that i've created just to make sure the app won't close in the middle).
if anyone else has questions, i can help.
I was wondering why not use android:configChanges="keyboardHidden|orientation" in every (almost every ;)) activity?
Goods:
no need to worry about your activity been rotated
it's faster
Not so nice:
need to change your layouts if they are depending on screen size (e.g. layouts with two columns or so)
Bad:
no flexible way to have different layouts on different orientation
not so good when using fragments
But if we don't use different layouts, why not?
Quick Background
By default, when certain key configuration changes happen on Android (a common example is an orientation change), Android fully restarts the running Activity to help it adjust to such changes.
When you define android:configChanges="keyboardHidden|orientation" in your AndroidManifest, you are telling Android: "Please don't do the default reset when the keyboard is pulled out, or the phone is rotated; I want to handle this myself. Yes, I know what I'm doing"
Is this a good thing? We shall soon see...
No worries?
One of the pros you start with is that there is:
no need to worry about your activity been rotated
In many cases, people mistakenly believe that when they have an error that is being generated by an orientation change ("rotation"), they can simply fix it by putting in android:configChanges="keyboardHidden|orientation".
However, android:configChanges="keyboardHidden|orientation" is nothing more than a bandaid. In truth, there are many ways a configuration change can be triggered. For example, if the user selects a new language (i.e. the locale has changed), your activity will be restarted in the same way it does by an orientation change. If you want you can view a list of all the different types of config changes.
Edit: More importantly, though, as hackbod points out in the comments, your activity will also be restarted when your app is in the background and Android decides to free up some memory by killing it. When the user comes back to your app, Android will attempt to restart the activity in the same way it does if there was some other configuration change. If you can't handle that - the user will not be happy...
In other words, using android:configChanges="keyboardHidden|orientation" is not a solution for your "worries." The right way is to code your activities so that they are happy with any restart Android throws at them. This is a good practice that will help you down the road, so get used to it.
So when should I use it?
As you mentioned there is a distinct advantage. Overwriting the default configuration change for a rotation by handling it yourself will speed things up. However, this speed does come with a price of convenience.
To put it simply, if you use the same layout for both portrait and landscape you're in good shape by doing the overwrite. Instead of a full-blown reload of the activity, the views will simply shift around to fill the remaining space.
However, if for some reason you use a different layout when the device is in landscape, the fact that Android reloads your Activity is good because it will then load up the correct layout. [If you use the override on such an Activity, and want to do some magical re-layout at runtime... well, good luck - it's far from simple]
Quick Summary
By all means, if android:configChanges="keyboardHidden|orientation" is right for you, then use it. But PLEASE be sure to test what happens when something changes, because an orientation change is not the only way a full Activity restart can be triggered.
From my point of view: If the layout is the same in both landscape and portrait mode - you might aswell disable one of the two in your app.
The reason why I state this is that I as a user expect the app to provide me with some benefit, when I change orientation. If it doesn't matter how I hold my phone, then I don't need the choice.
Take for instance an app where you have a ListView, and upon clicking a ListItem you want to be shown a detailed view for that item. In landscape you would od this by dividing the screen in two, having the ListView on the left and the detailed view on the right. In Portrait you would have the list in one screen and then change the screen to the detailed view when a ListItem is selected. In that case orientation change makes sense as well as different layouts.
I don see why.... occasional restarts are ok in my opinion... configChanges handles most cases for me... well maybe in some types of applications this can be problem but it depends really on type of app and how you restore state when app restarts... When one of my app restarts user is logged back and last activity opens by my code and user jus loses some steps to go back where he was but not big deal.. In other some state is always persisted and some state is always restored on restart. When activity restarted it had to be that app have not been used or something... so no problem at all... In game for example this can be problem maybe or in some other type of app I don't know...
I say that when you do it this way applications just works fine under normal circumstances. And code is much more readable without ton of logic needed for saving and restoring where u just can make new bugs and have to maintain it all the time... sure if android gets out of power and kill you application window it lose the context and starts again, but this happen just in special situations and on newer devices I belive this is more and more rare...
So kill me, but I use this across applications quite successfully...
android:configChanges="locale|keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
But I understand that for some special kind of applications it may be not good way but most of apps can live with this just OK.
Yeah I think pausing will make it quicker than releasing the player. Still have the pause though.
Have now found a solution that won't pause the song.
State in the manifest that you will handle the config change for screen orientation and then use the onConfigurationChanged method to load the layout file. By doing this in logCat I can see onPause, onCreate & onResume aren't called, and therefore the song isn't paused.
update the manifest to handle the orientation.
android:configChanges="orientation|screenSize"
add this code
#Override
public void onConfigurationChanged(Configuration newConfig) {
// TODO Auto-generated method stub
super.onConfigurationChanged(newConfig);
setContentView(R.layout.activity_main);
}
I used:
getWindow().addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
How do I resume to Default state (no-keep-on)?
I think this should do it:
getWindow().clearFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
See API for details.
If you instead set a flag android:keepScreenOn="true" (documentation) only on the views that need to keep the screen on, you wouldn't need to reset the flag manually.
Another approach
getWindow().setFlags(this.getWindow().getFlags() & ~WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
Also read this
and you can also set android:keepScreenOn="true" in the root View in xml.
Directly from documentation:
Note: You don't need to clear the FLAG_KEEP_SCREEN_ON flag unless you no longer want the screen to stay on in your running application (for example, if you want the screen to time out after a certain period of inactivity). The window manager takes care of ensuring that the right things happen when the app goes into the background or returns to the foreground. But if you want to explicitly clear the flag and thereby allow the screen to turn off again, use clearFlags(): getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON).
I have a Seekbar and I want to save the state to database when the progress is changed.
I am wondering in which event to put my code onProgressChanged vs. onStopTrackingTouch?
I am going to disagree with both mbaird and jqpubliq, for one simple reason: they assume the user is using a touchscreen.
Most Android devices have touchscreens. Not all will. For example, there are firms developing Android set-top boxes (think Android equivalents of Roku or Boxee Box). Most televisions are not touchscreens.
Now, if you want your application to only be usable with a touchscreen -- and you have set the appropriate <uses-configuration> elements in your manifest -- onStopTrackingTouch() may be reliable for detecting a progress change.
Personally, I would update the database on neither onProgressChanged() nor onStopTrackingTouch(), but at the point when the user does something positive to indicate they want to persist the current screen's contents -- pressing the BACK button, clicking a Save button, etc. But I certainly would not rely on onStopTrackingTouch() unless you are developing a touchscreen-only app.
I would use onProgressChanged if you need to update any elements of the UI as the user is sliding the progress bar.
I would wait for onStopTrackingTouch to actually update the database.
Unless you have reason to believe that the application will often crash in the middle of the gesture and you need to save where the user was at that time, I would recommend onStopTrackingTouch.
Is it possible to make an Activity temporarily not rotatable (like, turning it on/off in code, not in the manifest)?
One of my old apps crashes if you rotate while it's doing an HTTP lookup as the views are no longer attached when it returns.
One of these days I'll fix it proper, but in the mean time it'd be useful if I could just make the thing not-rotatable while it's doing the lookup.
I believe you can register to be notified of the orientation change events and override Activity.onConfigurationChanged. Register for orientation changes in the manifest with the configChanges attribute.
Then, of course, you can decide whether or not to rotate and call setRequestedOrientation.