Are Android system widgets within app configurable? - android

When I press one of the volume hardware buttons, Android's system is shown a depicted. Naturally this also happens when I press whithin my app.
Is it possible to configure the style of these Android system stuff like volume? Or at least when I open these system stuff in my app?
EDIT: As recommended in the comments, I've overwritten onKeyDown, but the adjustStreamVolume switches between 0 and 1 only.
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
when (event?.keyCode) {
KeyEvent.KEYCODE_VOLUME_UP -> {
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_RAISE, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE)
return true
}
KeyEvent.KEYCODE_VOLUME_DOWN -> {
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_LOWER, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE)
return true
}
else -> {
return super.onKeyDown(keyCode, event)
}
}
}
The streamVolume does not increase well.
Unfortunately, when I press continuously Volume_up, the 'getStreamVolume()' value remains t 1

Volume dialog
For the volume, it is very easy to replace the volume dialog with a custom one, from android-hide-volume-change-bar-from-device you can replace it with something simple such as a progressbar in your activity, because Android provide an interface for it.
Notification dialog
You can also (if you are very motivated) have a custom display for the incoming notifications. You will need to have a service implementing NotificationListenerService running, it will have to intercepts the notifications, and send them to the main activity to display them the way you want.
Other dialogs
Others, such as the power menu will not be changeable for obvious reasons.
Conclusion
You cannot modify the style of the android system without root permission, because it is encoded in the system app.
Android offers you different way to change its behavior but it has its limitations.
Here is an example for the volume:
main_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ProgressBar
android:id="#+id/progress_horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
style="#style/Widget.AppCompat.ProgressBar.Horizontal"/>
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
AudioManager manager;
ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
manager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
progressBar = findViewById(R.id.progress_horizontal);
updateVolume();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_VOLUME_UP:
updateVolume();
manager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
AudioManager.ADJUST_RAISE,
AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
return true;
case KeyEvent.KEYCODE_VOLUME_DOWN:
updateVolume();
manager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
AudioManager.ADJUST_LOWER,
AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
return true;
default:
return super.onKeyDown(keyCode, event);
}
}
private void updateVolume()
{
int currentVolume = manager.getStreamVolume(AudioManager.STREAM_MUSIC);
int maxVolume = manager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
progressBar.setProgress((int) ((float) currentVolume/maxVolume*100));
}
}
Edit
Some people said the original volume bar is still visible.
I directly tried the code I provided on my S10 Android 10 (Samsung framework) and the default volume bar is not visible. Therefore I also tried it on my S4 running LineageOS 10, and same result. No volume bar appear.
About the adjustStreamVolume or adjustVolume they both allow you to change volume channel but the adjustStreamVolume allow you to change a specific one for example, media, call etc. In my example it is only editing the media.

At application Level yes you can do anything because every action has an event, you can create your own actions with UI of your own choice on the events of your choosing, e.g hiding the STOCK VOLUME DIALOG and showing CUSTOM DIALOG, but at OS level no you can't.
Reason
Android Framework and any other architectural Component work on the
basics of events, like in Android OS if you do something, an event is
initialized and a broadcast is sent to all the framework and it can be
read by any application having right PERMISSIONS and IDS for
those Broadcasts, by using BROADCAST RECEIVERS and SERVICES in case of Notifications for special
broadcasts.
How can you achieve your goals
I will not tell you every function and method for what you want to do
but will tell you the recipe for achieving it, with the help of
Andoird's Official DOCs and with great people at Stackoverflow
For all the events you can you this overriding method
#Override
public boolean onKey**`YourKeyEvent`**(int keyCode, KeyEvent event) {
switch (event.getKeyCode()) {
case KeyEvent.Your_Event_One:
//your actions (perform code on some keyEvent)
break;
case KeyEvent.Your_Event_Two:
//your actions (perform code on some keyEvent)
break;
}
}
above code is great for most of the events but for some, you will be needing Broadcast Reciever aswell
LIST OF KEY_EVENTS (Android's Docs)
List Of Key Codes (Android's Code)
EDIT
For volume change please have a look at This
post, by using this post you can create a callback on volume rocker action, and then hide the stock dialog, and show your own, by using the service on the home screen.
NOTE: I've never been exposed to hiding the stock UI components in past so I am not sure about that part.

Related

Change Android volume bar

When you are in an Instagram story, and you decide to raise or lower the volume, this custom bar appears
Instead, the normal volume bar looks like this
I've researched ways to do it, but haven't found any.
How do I make this effect in Android Studio?
PD: I want to make this effect only when a person is using my application NOT to change the volume bar on the Android system
Use Key Event to find control of volume up and down button like this.
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_UP:
return true;
case KeyEvent.KEYCODE_VOLUME_DOWN:
return true;
default:
break;
}
return super.onKeyDown(keyCode, event);
}
And then create a custom seek bar and control the seek bar progress with the button control.
Hope it works.

How to disable Android gamepad default controls?

I'm trying to make an app which is controlled by a gamepad. I've gotten it to work alright, but Android has some default controls that it uses for navigation when a gamepad is plugged in, such as the B button takes you back a menu. I want to be able to use the buttons that Android has defaults for. Is there a way to disable the default Android controls? I can't find any thing about the default Android gamepad controls, let alone how to disable them.
I figured it out. For anyone who needs this in the future, here's how to do it. When you add in the onKeyDown override command, this is what it looks like.
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
return super.onKeyDown(keyCode, event);
}
As I understand it, that return line gives the Android system access to the button presses. However if you make it always return true, the Android system never sees the input. For example:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if(keyCode == KeyEvent.KEYCODE_BUTTON_A)
{
buttonAPressed = true;
}
return true;
}
I don't know if this is the best way to do it, but that's my work around to it. Hope this helps anyone that needs it!

How to show Android keyboard with symbols mode by default?

I have a EditText component, and, of course, if you click on it, the Android keypad is shown, allowing the user to input text. As far as I know, all Android software keyboards have (at least) a letter mode (ABC) and a symbols mode (?123). Their default view is the letter mode.
Now when the keypad is shown when the EditText component is clicked, I want the symbols mode to be shown by default. The user will still be able to switch to the letter mode.
Is there a way to achieve that? If yes, how?
I'm posting this because I don't think any of the answers actually address the question. The screenshot in the question does not correspond to a particular InputType's default state. So, switching InputTypes will not give you the layout from the screenshot.
(based on my research...)
Support for symbol input is not governed by any contract. One can very well leave symbols out when creating their own InputMethod. OR, they can add pagination support to provide access to 100s of symbols. Can this be bound by a contract? May be. But, it isn't at present.
Input method framework does not allow direct communication between the client and the IME. All communication happens either through the InputMethodManager or through InputConnection — a one-way channel. Switching to symbols using ?123 is, however, an internal event — not a defined state/action. Client applications cannot switch to it. There's no public (or hidden) API to make this happen.
InputType indicates something entirely different to an IME. Not sure why everyone is recommending its use. You may of course find that a particular InputType provides most of the required keys. But that isn't the same as show[ing] Android keyboard with symbols mode by default.
Possible workaround:
We'll create a custom EditText. We don't have to. It'll just keep everything in one place, and save us from copy-paste nightmare.
public class CusEditText extends EditText {
private final int mDefinedActionId;
public CusEditText(Context context, AttributeSet attrs) {
super(context, attrs);
// Corresponds to 'android:imeActionId' value
mDefinedActionId = getResources().getInteger(R.integer.definedActionId);
setOnEditorActionListener(new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
Log.i("CusEditText", "onEditorAction, actionId = " + actionId);
// Only bother if (...)
if (actionId == mDefinedActionId) {
// Check if current InputType is NUMBER
if ((getInputType() & InputType.TYPE_CLASS_NUMBER) != 0) {
// Toggle
setImeActionLabel("NUM", mDefinedActionId);
setInputType(InputType.TYPE_CLASS_TEXT);
} else {
// Current InputType is TEXT // Toggle
setImeActionLabel("ABC", mDefinedActionId);
setInputType(InputType.TYPE_CLASS_NUMBER);
}
// We've handled this
return true;
}
// Let someone else worry about this
return false;
}
});
}
}
Next, we need to define definedActionId. Open or create res/values/integers.xml and add:
<integer name="definedActionId">-100</integer>
-100 is an arbitrary value. I checked EditorInfo and the actionIds (IME_ACTION_XXXX) were >= 0. -100 seems like a good candidate.
In xml, your layout will look like:
<com.your.packagename.CusEditText
android:layout_width="blah"
android:layout_height="blah"
android:inputType="number"
android:imeActionId="#integer/definedActionId"
android:imeActionLabel="ABC"/>
<!-- Probably use #string resource in place of ABC -->
There's not much to explain. IME will launch in NUMBER mode. Instead of a checkmark icon, it'll display ABC. On click, we intercept the actionId and toggle between NUMBER and TEXT input. We're using setInputType(...) because it not only updates the InputType, it also restarts the IME with changes. setRawInputType(...) only updates the InputType.
Issues:
As you can tell, this isn't really a solution. If the user closes the keyboard(using the back button) in TEXT mode, the keyboard will remain in the TEXT mode when they open it again. To go to the NUMBER mode, user will have to click NUM. Also, in TEXT mode, user will see NUM as the action, along with ?123 option. This doesn't break anything, but does take away from the UX.
We can't do anything about ?123 showing in TEXT mode for reasons listed above. But, we can try to make sure that the keyboard always opens in the NUMBER mode. I'll provide a rough sketch of how we'll do that. Its not straight-forward since we (developers) are not privy to events such as keyboard closing or opening. Updated CusEditText:
public class CusEditText extends EditText {
private final int mDefinedActionId;
private long mLastEditorActionTime = 0L;
public CusEditText(Context context, AttributeSet attrs) {
super(context, attrs);
// Corresponds to 'android:imeActionId' value
mDefinedActionId = getResources().getInteger(R.integer.definedActionId);
setOnEditorActionListener(new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
Log.i("CusEditText", "onEditorAction, actionId = " + actionId);
// Only bother if (...)
if (actionId == mDefinedActionId) {
// setInputType(...) will restart the IME
// and call finishComposingText()
// see below
mLastEditorActionTime = SystemClock.elapsedRealtime();
// Check if current InputType is NUMBER
if ((getInputType() & InputType.TYPE_CLASS_NUMBER) != 0) {
// Toggle
setImeActionLabel("NUM", mDefinedActionId);
setInputType(InputType.TYPE_CLASS_TEXT);
} else {
// Current InputType is TEXT // Toggle
setImeActionLabel("ABC", mDefinedActionId);
setInputType(InputType.TYPE_CLASS_NUMBER);
}
// We've handled this
return true;
}
// Let someone else worry about this
return false;
}
});
}
#Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
InputConnection inputConnection = super.onCreateInputConnection(outAttrs);
return new CusInputConnectionWrapper(inputConnection, false);
}
private class CusInputConnectionWrapper extends InputConnectionWrapper {
private CusInputConnectionWrapper(InputConnection target, boolean mutable) {
super(target, mutable);
}
#Override
public boolean finishComposingText() {
Log.i("CICW", "finishComposingText");
// Ignore finishComposingText for 1 second (1000L)
if (SystemClock.elapsedRealtime() - mLastEditorActionTime > 1000L) {
if ((getInputType() & InputType.TYPE_CLASS_NUMBER) == 0) {
// InputConnection is no longer valid.
// Switch back to NUMBER iff required
setImeActionLabel("ABC", mDefinedActionId);
setInputType(InputType.TYPE_CLASS_NUMBER);
}
}
return super.finishComposingText();
}
}
}
Again, code is self-explanatory. We create a InputConnectionWrapper and listen for the finishComposingText() callback. If we're manually switching between TEXT and NUMBER, we use a flag since finishComposingText() will automatically be called. Else, we check if input type is set to TEXT and change it to NUMBER. I am not sure if finishComposingText() is the right method for interpreting keyboard closing/opening. Testing on API 21, vanilla android, this seems to work. More tests will be required.
I really hope someone can come up with a better, more robust solution than this - or modify my workaround so that it doesn't look like one.
Summary
Task at hand is to provide functionality of switching between NUMBER & TEXT input modes around existing Input Method Engines (IMEs). The first approach was to use imeActionLabel & imeActionId in the switching mechanism. This approach worked well with Google's keyboard (this is the imeActionLabel), but failed with Samsung's - imeActionLabel failed to show up in portrait (without extract). Possible workaround is to include the toggle button in the app's own UI.
Even with Google's keyboard, the letters (text) fail to show up when the mode switches back to NUMBER after inputting letters. This problem was fixed (at least on tested devices) by using flag flagNoExtractUi which prevents the IME from entering fullscreen mode in landscape orientation.
Final solution (pending implementation & testing)
The IME starts in the NUMBER input mode (95% use-cases involve number input)
A button is added to app's UI (next to the EditText) for switching between NUMBER & TEXT mode
User can switch from NUMBER to TEXT without any restrictions. Switching back from TEXT to NUMBER requires that no alphabets have been added.
InputType is preserved between keyboard closing & reopening. Example: If the user switches to TEXT mode and closes the keyboard, it will open in the TEXT mode. The InputType is not reset.
For more information about the approaches tried, refer to this discussion thread.
Screenshots
Default (NUMBER):
Switched to TEXT:
Recorded video link
I agree it is an InputType. If you want to show only numbers to your user then you would add the following to you xml document for your edit text:
android:inputType="number"
However if you set it as number then the user has to enter a number. But you can add additional types as well like numbers and email addresses such as:
android:inputType="number|textEmailAddress"
Check out http://developer.android.com/reference/android/text/InputType.html for more options. You can also check out what eclipse or android studio shows you under "inputType"
I believe you are looking to set the InputType of your edit text.
http://developer.android.com/reference/android/text/InputType.html
I'm not sure which you would use though you may have to play around a bit.
The only way to do this is by setting the inputType of your EditText.
If you want to set this property in the onCreate() (or inside a custom View's constructor) you can use the method setRawInputType():
mEditText.setRawInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
Otherwise, if you need to set this property after the onCreate() (or after a custom View's constructor), you can use the method setInputType():
mEditText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
Obviously you can also specify the property at XML level:
android:inputType="number|numberDecimal"
You can play around with different flags to find the best composed filter.
Programmatically it is possible with little bit of tweak to the usual flow. First you have to set editText as:
editText.setInputType(InputType.TYPE_CLASS_NUMBER);
Then you have to listen for keyevent. On pressing of pound set the InputType again to InputType.TYPE_CLASS_TEXT. This should work as it works for me.
editText.setOnKeyListener(new View.OnKeyListener()
{
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
Log.d("KeyBoard", "Keyboard Test Key Hit");
switch (keyCode) {
KeyEvent.KEYCODE_POUND:
if(editText.setInputType(InputType.TYPE_CLASS_TEXT);
{
editText.setInputType(InputType.TYPE_CLASS_TEXT);
return true;
}
Same thing I've answered i: EditText with number keypad by default, but allowing alphabetic characters

Disable the Search Button (Quick Search Box) in Android

I'm developing an application right now and I need to disable the quick-search-box as somehow it dismisses my dialog boxes that request info to keep people who are not supposed to be using my application out [its in development, and its on the market - it makes it much easier to keep people up to date]. Listeners for all types of dismissing dialogs are never triggered - and I don't know why. I've looked everywhere and I get no result on how to disable this. (2.1 and up).
How to disable QSB..? was a good start, but it doesn't work. I don't know why google insists I use this... I have absolutely no need for this in my application.
How can I go about fixing this... or do I have to try another sort of DRM?
You can block the search on your activity or dialog by implementing this and returning false:
public boolean onSearchRequested() {
return false;
}
UPDATE:
Code works on dialogs, too
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode==KeyEvent.KEYCODE_SEARCH && event.getRepeatCount() == 0)
{
return true;
}
else
{
return false;
}
}
Returning true means that we are handling the Search Event.

Reliable way to know when android soft keyboard resigns (callback that works on every phone)

We are working on our first android app and it has been a very enjoyable experience so far. It is almost complete, but before release we are having some considerations ,mainly about android soft keyboard.
We have a couple of EditText fields that are used to enter numbers. We would like to capture the event when user presses enter, and do some calcuations and saving on this callback.
The problem is that we are not getting a fixed event as different phones have different keyboards. Some have 'Done' button and our HTC phones have 'Enter' buttons. We tried using the imeOptions as 'done' but that had no effect on the HTC phones.
We also know that the keyboard can be dismissed by hitting the back button. So my question is if there is a reliable way to know when the user has stopped entering or when the keyboard is hidden, just like textFieldShouldReturn callback in iphone sdk(which will always fire when keyboard goes down, independent of what key caused it to go down)..
In other words, how an android developer handles soft keyboard? I check for KeyEvent.KEYCODE_ENTER on editText onClick() event and do my tasks there.It is working on my HTC android, but not on my friends Nexus phone, which has a done button instead of enter. There onClick is not even called. How a developer handles this?
EDIT: After losing half of my hair, and with the help of some good friends here
I have tried all your suggestions but at the end by using onEditorActionListener along with onKeyListener method did the trick for me. In onEdit callback of onEditorActionListener I checked for KeyCode ACTION_DONE, which did get called on keyboards with done button. On keyboards which has enter onKey gets called. In onKey method I checked for KEYCODE_BACK also, so that hardware back press event also can be handled. I haven't yet found out a android device with done and enter on the keyboard (seriously), still I even handled that case with a flag. Thanks #Femi for suggesting onEditorActionListener, and thanks for all friends for your help. But the answer to my original question
Q: Is there an reliable and easier way to know android soft keyboard resigns (callback that works on every phone)
Ans : No, All methods suggested here and all methods suggested on other sites are not straightforward. And I think handling an event for keyboard return key is the most basic thing for any operating system. Google, are you there?
Since it seems that you are catching the KEYCODE_ENTER event, you might be able to use this: http://developer.android.com/reference/android/widget/TextView.html#setOnEditorActionListener%28android.widget.TextView.OnEditorActionListener%29. In theory this will let you detect whatever the input method end action is (whether its back, done, enter, or whatever) and respond to it.
Let me know if that works for you.
Wouldn't you also need to perform those calculations when the user is leaving the TextView on a hardware keyboard? I wouldn't focus on the keyboard, but on the TextView itself. If so, what you probably want is setTransformationMethod
You'd have to implement a custom TransformationMethod, specifically the method getTransformation, which transforms a source CharSequence into another one. You can then use the onFocusChanged to apply this only when the focus is lost for that TextView.
I found a solution on this SO page:
Intercept back button from soft keyboard
The answer from mhradek has 0 votes but it seems to be working.
The idea is to extend the base layout of your activity so that you can override the dispatchKeyEventPreIme method and do what you want regarding the KeyEvent passed. Note that you are responsible for managing the soft keyboard.
I am using it and I can definitely intercept key strokes (the back button for example) without the soft keyboard "eating" them. I have yet to play more with it in order to see what is possible and what is not.
I hope it helps.
Have you tried implementing custom EditText view, where you override dispatchKeyEventPreIme? Just like in answer posted by Arnaud (referencing Intercept back button from soft keyboard) but instead of using custom layout use custom EditText and override:
#Override
public boolean dispatchKeyEventPreIme(KeyEvent event) {
if(KeyEvent.KEYCODE_BACK == event.getKeyCode()) {
//this hides soft keyboard in super.dispatchKeyEventPreIme(event)
}
return super.dispatchKeyEventPreIme(event);
}
I suggested this solution in this question
I cant believe Google doesnt have a keyboard independant callback for this case
Wow, I cant believe that neither. I am having a similar problem at the moment.
In addition to the IME ACTION I check for focus changes on the EditFields. This is fine for most of the time, but won't work always.
I found a way to be notified when the keyboard is being hidden, but it's not a complete solution yet (and I'm not sure whether it's a good idea), but I don't have the time to continue right now, so I thought I can drop the start of the idea here...:
Write your own EditText(extend EditText) and override onCreateInputConnection. In your onCreateInputConnection return your own implementation of InputConnection (you can simply extend BasicInputConnection.
The InputConnections "finishComposingText()" method is always called when the keyboard is being hidden (also when the user presses the back-key).
This is the code, and maybe someone else has an idea, why the entered text is not shown in this editfield ;-)
public class MyEditText extends EditText{
public MyEditText(Context context) {
super(context);
}
public MyEditText(Context context, AttributeSet attrs) {
super(context);
}
public MyEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
System.out.println("onCreateInputConnection, "+outAttrs.actionId);
return new MyInputConnection(this,true);
}
private class MyInputConnection extends BaseInputConnection{
public MyInputConnection(View targetView, boolean fullEditor) {
super(targetView, fullEditor);
}
#Override
public boolean finishComposingText() {
System.out.println("FINISH");
return super.finishComposingText();
}
}
}
JPM
I have not tried this but, reading the documentation, it seems possible.
// From an activity, you can call
if (getResources().getConfiguration().keyboardHidden == Configuration.KEYBOARDHIDDEN_YES) {
// your code here
}
This code is working fine for me with HTC and default Android keyboard:
editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
// handle enter key on keyboard
if (actionId == EditorInfo.IME_ACTION_SEND ||
(event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_DOWN)) {
if (uid != null) {
// hide keyboard
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
// perform other stuff
return true;
}
}
return false;
}
});
Using the following in the editText´s XML:
android:imeOptions="actionSend"
Of course you could also use something else like send, just make sure to change it in both the XML and Java code.

Categories

Resources