I have developed an app which uses my own custom keyboard (well, a view that looks like a keyboard and behaves like a keyboard anyway). One thing I've yet to figure it out is how to make it play the default soft keyboard 'click' sound when the buttons are pressed.
Is there any easy way to do this?
I would like to use the keyboard click sound that comes with the phone rather than providing my own. As different phones might have different keyboard click sounds, I would like to keep my application consistent. Ultimately, I want to reflect the same settings the user has chosen in their global keyboard settings (play/not play sounds, vibrate/not vibrate, etc).
I have found a solution to this. All I needed to do was implement a OnTouchListener on the button and use the AudioManager.playSoundEffect() public method. Code is shown below:
AudioManager am = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
float vol = 0.5; //This will be half of the default system sound
am.playSoundEffect(AudioManager.FX_KEY_CLICK, vol);
if (isSetVibration) {
if (Build.VERSION.SDK_INT >= 26) {
((Vibrator) getSystemService(VIBRATOR_SERVICE)).vibrate(VibrationEffect.createOneShot(50, VibrationEffect.DEFAULT_AMPLITUDE));
} else {
((Vibrator) getSystemService(VIBRATOR_SERVICE)).vibrate(50);
}
} else {
if (Build.VERSION.SDK_INT >= 26) {
((Vibrator) getSystemService(VIBRATOR_SERVICE)).vibrate(VibrationEffect.createOneShot(0, VibrationEffect.DEFAULT_AMPLITUDE));
} else {
((Vibrator) getSystemService(VIBRATOR_SERVICE)).vibrate(0);
}
}
Related
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.
I coded an Android app, in which it has two buttons, one for mute the music_player and other for unmute it. But when I press the mute button two times in order to increase the media volume I need to press unmute button two times. How to avoid this? I want to unmute the media volume no matter how many times I mute the media volume. I used the following code:
Mute:
AudioManager am = (AudioManager)MainActivity.this.getSystemService(Context.AUDIO_SERVICE);
am.setStreamMute(AudioManager.STREAM_MUSIC, true);
Unmute:
AudioManager am = (AudioManager)MainActivity.this.getSystemService(Context.AUDIO_SERVICE);
am.setStreamMute(AudioManager.STREAM_MUSIC, false);
Editor's note: The two code segments above are identical. That's probably incorrect.
You may specify a boolean flag isMute and use it to toggle mute by one button just like this:
boolean isMute = false;
Button mMuteButton;
...
mMuteButton.setOnclickListener(
new OnClickListener {
public void onClick(View v) {
AudioManager am = (AudioManager)MainActivity.this.getSystemService(Context.AUDIO_SERVICE);
am.setStreamMute(AudioManager.STREAM_MUSIC, !isMute);
isMute = !isMute;
}
});
Or if you extremely want to use two buttons, so just disable one after mute or unmute
Is there any way to show software keyboard with USB keyboard connected (in my case RFID reader)?
I tried to force show it using InputManager (with these or similar parameters), but with no luck
((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).toggleSoftInput(InputMethodManager.SHOW_FORCED,0);
Important notice - I know that there is a button in status/system bar to show it, but this button is not visible to user (Kiosk app).
You need to override the InputMethodService method onEvaluateInputViewShown() to evaluate to true even when there is a hard keyboard. See onEvaluateInputShown() and the Soft Input View section of InputMethodService. Try creating your own custom InputMethodService class to override this method.
EDIT: The source for onEvaluateInputShown() should help. The solution should be as simple as creating your own class that extends InputMethodService and overriding this one method, which is only a couple of lines long. Make sure to add your custom service to your manifest as well.
From Source:
"Override this to control when the soft input area should be shown to the user. The default implementation only shows the input view when there is no hard keyboard or the keyboard is hidden. If you change what this returns, you will need to call updateInputViewShown() yourself whenever the returned value may have changed to have it re-evalauted and applied."
public boolean onEvaluateInputViewShown() {
Configuration config = getResources().getConfiguration();
return config.keyboard == Configuration.KEYBOARD_NOKEYS
|| config.hardKeyboardHidden == Configuration.KEYBOARDHIDDEN_YES;
}
Here are the possible configurations you can check for. Configuration.KEYBOARD_NOKEYS corresponds to no hardware keyboard. This method returns true (soft keyboard should be shown) if there is no hardware keyboard or if the hardware keyboard is hidden. Removing both of these checks and simply returning true should make the software keyboard visible even if a hardware keyboard is attached.
Try (not tested):
public boolean onEvaluateInputViewShown() {
return true;
}
Since this return value will not change, you won't need to call updateInputViewShown() yourself. If you modify this method differently, be sure to remember this detail.
The soft keyboard can have unpredictable behaviour on different platforms. First in your code, ensure you have an editable input control. Eg, if you have an EditText, you could use:
((InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE))
.showSoftInput(myEditText, InputMethodManager.SHOW_FORCED);
However, you can just show and hide it whenever you want using:
//show keyboard:
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
//hide keyboard :
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
You could also add any of these events inside OnCreate or some other method of the controls.
If however for some reason any of the above fails, your best option might be to use an alternative keyboard, e.g. Compass Keyboard,
OR
You could even build yours:
See an example of a keyboard implementing the inputmethodservice.KeyboardView
You might also want to take a look at the GingerBread Keyboard source.
If your app has the WRITE_SECURE_SETTINGS permission (available to system apps or Android Things apps) it can set the show_ime_with_hard_keyboard system setting which will enable soft keyboard even if a hard keyboard is plugged:
Settings.Secure.putInt(getContentResolver(), "show_ime_with_hard_keyboard", 1);
This worked in my app, interestingly, also an kiosk app.
This is a bit stripped, I did some checks beforehand, whether IMM is null and such.
((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).toggleSoftInputFromWindow(someInputView.getApplicationWindowToken(), InputMethodManager.SHOW_FORCED, 0);
according to this https://stackoverflow.com/a/24287780/2233069, I made working solution for Kiosk mode.
boolean hardwareKeyboardPlugged=false;
....
mEditText.setOnFocusChangeListener(this);//in onCreate()
....
#Override
public void onResume() {
//protect from barcode scanner overriding keys
hardwareKeyboardPlugged=(getResources().getConfiguration().hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO);
super.onResume();
}
....
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus)
if (hardwareKeyboardPlugged){
//protect from barcode scanner overriding keys
hardwareKeyboardPlugged=false;
((InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE)).showInputMethodPicker();
Toast.makeText(this, "USB device detected. Turn OFF hardware keyboard to enable soft keyboard!", Toast.LENGTH_LONG).show();
}
}
I have such a problem. I am writing Adobe AIR application for Android device. And I need to make device screen not to be dimmed. I'm making it with SystemIdleMode.KEEP_AWAKE this function for a minute-to five. But after that, I make it SystemIdleMode.NORMAL mode and it immediately dimmed. I want it to be dimmed in some standart time. Like after 30 seconds after that time, when I swiched off KEEP_AWAKE mode. How can I do that? Thanx.
public static function (isEnabled):void
{
if(isEnabled)
{
NativeApplication.nativeApplication.systemIdleMode = SystemIdleMode.KEEP_AWAKE;
}
else
{
NativeApplication.nativeApplication.systemIdleMode = SystemIdleMode.NORMAL;
}
}
I solved this issue in such a way: I switch to SystemIdleMode.NORMAL mode only after that, when user click on the screen. It gives me aditional 30 seconds to not switch screen to dimmed immediatly.
I am developing a game using Cocos2d FrameWork in Android.
I encountered a problem while testing on Motorola Xoom.
What I want to do :
When User pressed Volume up and Volume down Button. All the Animation should play with sound .
But What actually Happened:
When I pressed volume up down button on Motorola Xoom than My Game Lost Focus and all Animation Paused but sound is playing according to the volume button settings.
This is only when I test my Application in Honey Comb OS.
I am using onWindowFocusChanged method to Resume Game Play.
Anyone having encounter this type of problem ?
Please let me know if anyone have solution for this .
Thanks.
i found answer myself ..
Here is the solution of this issue ..
public void onWindowFocusChanged(boolean hasFocus)
{
synchronized(sGLThreadManager) {
//mHasFocus = hasFocus;
mHasFocus = true;
sGLThreadManager.notifyAll();
}
if (LOG_SURFACE)
{
Log.i("Main thread", "Focus " + (mHasFocus ? "gained" : "lost"));
}
}
just change mHasFocus = true in GLSurfaceView class of Cocos2d android ...