Each time my Optionsmenu opens (onCreateOptionsMenu(..) is called),
I get these warnings:
"No keyboard for id 0"
and
"Using default keyMap:
/system/usr/keychars/qwerty.kcm.bin"
I couldn't find out what they mean, does anyone know ? I didn't like this answer.
Here's the simple code I'm using:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.optmenu_start, menu);
return true;
}
and the optmenu_start.xml:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/optmenu_prefs"
android:title="#string/optmenu_prefs"
android:icon="#drawable/icon_menu_prefs"
/>
<item
android:id="#+id/optmenu_help"
android:title="#string/optmenu_help"
android:icon="#drawable/icon_menu_help"
/>
</menu>
Google's answer is
" The log is normal; it happens the first time a keymap is needed for a device
in a process. "
http://groups.google.com/group/android-developers/browse_thread/thread/477caf755085b108
So therefore if you started Activity2 before Activity1 you would see the warning in Activity2 and not Activity1!
As I said I think a lot of developers get this message and it's just a warning not an error; it can be ignored.
As #Blundell said, it's normal.
But it always consumes the first keyPressed event.
Finally, I add this on init:
setFocusableInTouchMode(true);
I don't know why, but this warning message never annoys me again.
Related
My old app has one simple menu on the main activity. It has only a few simple options, for instance "About" causing a popup with some info about the app.
It works perfectly on emulator Nexus One (API23), because there is an emulated physical menu button.
However, on most modern phones, there is no button, which means that my menus cannot be accessed.
I actually vaguely remember running it on a phone years ago which didn't have a menu button, yet somehow one could still access the menus. I may remember wrong.
(I started digging into this some days ago, and started modifying my code, the main activity inheriting from something more posh than Activity, which then caused some older API versions to be left out - and things quickly spun out of control. After hours of "maven gradle settings" and "Support Library" stuff and many pages of "AAPT2 errors" and messing up my whole system trying to fix that, I had to throw everything away and get a fresh clone from the repo. Fortunately I could also repair the other changes I had made to the system.)
How does one convert an old-style app menu to work on modern phones? It doesn't have to be fancy.
/** Setup menu */
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return true;
}
/** Handle menu clicks */
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.action_about:
final SpannableString s =
new SpannableString(getApplicationContext().getText(R.string.about));
Linkify.addLinks(s, Linkify.ALL);
AlertDialog d = new AlertDialog.Builder(this)
.setIcon(android.R.drawable.ic_dialog_info)
.setTitle("About")
.setMessage(s)
//.setView(message)
.show();
((TextView)d.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
return true;
default:
new AlertDialog.Builder(this)
.setIcon(android.R.drawable.ic_dialog_info)
.setTitle("Currently not used.")
.show();
return super.onOptionsItemSelected(item);
}
}
I'll admit that I no longer understand all the details above from years ago.. it worked, so I never paid it much attention. It looks a bit wordy... probably there are simpler ways to do it.
This is menu/main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/action_settings"
android:orderInCategory="100"
android:title="#string/action_settings"/>
<item
android:id="#+id/action_about"
android:orderInCategory="3"
android:title="About"/>
<item
android:id="#+id/action_manual"
android:orderInCategory="4"
android:title="Manual"/>
</menu>
Maybe there is some "theme" to just add somewhere that makes the menu button show up somewhere on the screen, and that's that? (I know I am optimistic. :))
Everything looks fine.
I think your problem is because you are extending Activity.
change Activity to AppComatActivity.
and change your appThem to android:theme="#style/Theme.AppCompat.Light.DarkActionBar"
Note:
To use the AppCompatActivity, make sure you have the Google Support Library downloaded (you can check this in your Tools -> Android -> SDK manager). Then just include the gradle dependency in your app's gradle.build file:
compile 'com.android.support:appcompat-v7:27.0.2'
SOLUTION:
The only way to a solution that I could find was to create a completely new project with default settings in the latest Android Studio. This gives a "latest fashion" setup. Then I moved code in from the old project manually.
Everything now works perfectly!
ISSUES / REASONS:
As mentioned in the comment section above, every attempt I made to modernize the code resulted in a maze of problems. It was an old project, from way back when Android Studio was not even in Beta stage. Hence, it was based on Eclipse. The current Android version back then was Jelly Bean (Kitkat was just released).
In summary, we had an ancient project based on an older IDE. Perhaps it would be doable to convert a modern Eclipse project into Android Studio. Perhaps it would be doable to convert an older AS project into a modern one. However, performing both these major jumps at the same time was too great a challenge for me.
Another issue which has nothing to do with the old code, but which confused the matter greatly is that something called AAPT2 currently for whatever reason assumes american characters only in the search path to the .gradle directory. I use the word "assumes", because if the characters are anything else, you get pages of errors in the build log. None of the errors point very clearly to the reason.
AFAIK I don't even use AAPT2! After some sleepless nights, I solved it by changing the global setting in Android Studio to simply use another path.
I am working on to avoid cut/copy/paste in smart phone (for tablet its fine).
Its fine in port mode but coming in land mode EditText shows a Button Next.
after selecting the text, next button converts into Edit Button which has copy,cut and paste option.
So is there any way to disable cut/copy after rotation when edit button appears.
i am following this link.
How to disable copy/paste from/to EditText
I think you can use this:
http://developer.android.com/reference/android/widget/TextView.html#attr_android:imeOptions
With the flag:
flagNoAccessoryAction
Used in conjunction with a custom action, this indicates that the action should not be available as an accessory button when the input method is full-screen. Note that by setting this flag, there can be cases where the action is simply never available to the user. Setting this generally means that you think showing text being edited is more important than the action you have supplied.
Corresponds to IME_FLAG_NO_ACCESSORY_ACTION.
I would insist you to disable the long click on the EditText as that Edit button appears when you long press on the selected text in the EditText.
et_text.setLongClickable(false);
Also, you can clear the ClipboardManager, so that if you already have something that is already copied to ClipBoard will be cleared using,
ClipboardManager manager = (ClipboardManager)
getSystemService(Context.CLIPBOARD_SERVICE);
manager.setText("");
Try this ..
your_edit_text.setCustomSelectionActionModeCallback(new Callback() {
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
public void onDestroyActionMode(ActionMode mode) {
}
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return false;
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
});
Try using these two lines. It may help you:
EditText.setFocusable(false);
EditText.setFocusableInTouchMode(false);
as we don't know what u tried so far..and what you actually doing in your code...beside that..here is a link ...similar to your question , i think this will help you out..
Disabling the fullscreen editing view for soft keyboard input in landscape?
#Cobra - set EditText.setEditable(false); in your code, or you set this property in your xml as well.
this property done well, but if any case this won't work ..set setFocusable also false..
this solution work for me..
I asked this question 6 years ago. In the meantime Android development best practices have changed, and I have become a better developer.
Since then, I have realized that using the onClick XML attribute is a bad practice, and have removed it from any code base I work on.
All of my click handlers are now defined in the code of the app, not the XML layouts!
My reasons for never using onClick are
it is easy to make a mistake in the value of the onClick XML attribute, which will then result in a run-time error
a developer might refactor the name of the click handler method, without realizing it is called from a layout (see reason 1)
finding out which method is actually being called is not always obvious. Especially if the layout is being used by a Fragment
separating the concerns of layout vs behavior is good. Using onClick mixes them up, which is bad!
I hope I have convinced you to never use onClick in a layout :) !
Below is my original question, which is a pretty good illustration of why using onClick is a bad idea.
===
I'm defining menu items in XML, and trying to use the onClick attribute that was added in API 11. When the Activity is launched in an emulator running 4.0.3, the following Exceptions occur:
FATAL EXCEPTION: main
android.view.InflateException: Couldn't resolve menu item onClick handler
onFeedbackMenu in class android.view.ContextThemeWrapper
...
Caused by: java.lang.NoSuchMethodException: onFeedbackMenu
[interface com.actionbarsherlock.view.MenuItem]
at java.lang.Class.getConstructorOrMethod(Class.java:460)
I don't understand what is causing the Exception, since the following method is defined in my Activity
import com.actionbarsherlock.view.MenuItem;
...
public void onFeedbackMenu( MenuItem menuItem ) {
Toast.makeText( this, "onFeedBack", Toast.LENGTH_LONG ).show();
}
My XML menu definition file contains:
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
...
<item
android:id="#+id/menu_feedback"
android:icon="#drawable/ic_action_share"
android:showAsAction="ifRoom"
android:title="#string/menu_feedback"
android:onClick="onFeedbackMenu" />
</menu>
For backwards compatibility I am using ActionBarSherlock, and also getting a very similar Exception when I run the App on 2.3.x.
This is a more Complete version of the Stack trace
FATAL EXCEPTION: main
android.view.InflateException: Couldn't resolve menu item onClick handler
onFeedbackMenu in class android.view.ContextThemeWrapper
at com.actionbarsherlock.view.MenuInflater$InflatedOnMenuItemClickListener.<init>(MenuInflater.java:204)
at com.actionbarsherlock.view.MenuInflater$MenuState.setItem(MenuInflater.java:410)
at com.actionbarsherlock.view.MenuInflater$MenuState.addItem(MenuInflater.java:445)
at com.actionbarsherlock.view.MenuInflater.parseMenu(MenuInflater.java:175)
at com.actionbarsherlock.view.MenuInflater.inflate(MenuInflater.java:97)
...
Caused by: java.lang.NoSuchMethodException: onFeedbackMenu
[interface com.actionbarsherlock.view.MenuItem]
at java.lang.Class.getConstructorOrMethod(Class.java:460)
at java.lang.Class.getMethod(Class.java:915)
at com.actionbarsherlock.view.MenuInflater$InflatedOnMenuItemClickListener.<init>(MenuInflater.java:202)
... 23 more
I found a solution that worked for me.
Usually the onClick attribute in a layout has the following method
public void methodname(View view) {
// actions
}
On a menu item (in this case Sherlock menu) it should follow the following signature:
public boolean methodname(MenuItem item) {
// actions
}
So, your problem was that your method returned void and not boolean.
In my case, the AndroidManifest.xml of my application (kick-started by the default Eclipse assistant) contained android:theme="#style/AppTheme" in the <application> block.
When debugging the cause of the problem, it turned out that the line
mMethod = c.getMethod(methodName, PARAM_TYPES);
in android.view.MenuInflater/InflatedOnMenuItemClickListener was called with c not being my Activity class but a dubious android.view.ContextThemeWrapper (which of course doesn't contain the onClick handler).
So, I removed the android:theme and everything worked.
Although this is a bit out of date, here is the reason for the exception. When you look into the sources of android API 15 (4.0.3-4.0.4) in the class MenuInflater you will see this method:
public InflatedOnMenuItemClickListener(Context context, String methodName) {
mContext = context;
Class<?> c = context.getClass();
try {
mMethod = c.getMethod(methodName, PARAM_TYPES);
} catch (Exception e) {
InflateException ex = new InflateException(
"Couldn't resolve menu item onClick handler " + methodName +
" in class " + c.getName());
ex.initCause(e);
throw ex;
}
This is were the exception happens, as Junique already pointed out. However the removing of the app theme is just a workaround and no real option. As we see the method tries to find the Callback method on the class of the context item passed. So instead of calling getMenuInflater() in onCreateOptionsMenu you should call new MenuInflater(this), so that this is passed as a context and then the code will work.
You can still use getMenuInflater() for other api versions if you just use an if statement like this:
if (Build.VERSION.SDK_INT > 15)
inflater = getMenuInflater();
else
inflater = new MenuInflater(this);
I don't actually know if the bug happens in api versions under 15 too, so i just generally used the save version.
In my case the problem was that I had both onClick in my menu XML and an onCreateOptionsMenu in my Activity. My onClick was actually faulty (because it pointed to non-existent methods) but I didn't notice this at first because I was testing under Android 2.x, where onClick is not supported and ignored. Once I tested on 4.x though, I started getting this error.
So basically, don't use onClick if you plan on deploying under Android 2.x. It will silently ignore your onClick values until you try running on 3.0+.
I found that I had the same problem with the ActionBar menu items, and their onClick events. What i discovered is that the workstation I'm developing in had run out of memory and needed to be rebooted. The Android VM is now able to resolve the method name referenced.
Your method must accept a MenuItem as its only parameter per here.
public void onMenuItemClickMethod(MenuItem menuItem){
// Do stuff here
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.activity_main, menu);
MenuItem item = menu.findItem(R.id.menu_open);
if (item == null)
return true;
item.setOnMenuItemClickListener
(
new MenuItem.OnMenuItemClickListener ()
{
public boolean onMenuItemClick(MenuItem item)
{ return (showDirectory(item)); }
}
);
return true;
}
public boolean showDirectory (MenuItem item)
{
CheckBox checkBox = (CheckBox) findViewById (R.id.checkBox1);
checkBox.setChecked(true);
}
I'd like to have all of the menu items that don't fit into the ActionBar go into the overflow menu (the one that is reached from the Action Bar not the menu button) even on devices that do have a Menu button. This seems much more intuitive for users than throwing them into a separate menu list that requires the user to jump from a touch(screen) interaction to a button based interaction simply because the layout of the ActionBar can't fit them on the bar.
On the emulator I can set the "Hardware Back/Home Keys" value to "no" and get this effect.
I've searched for a way to do this in code for an actual device that has a menu button but can't fine one. Can anyone help me?
You can also use this little hack here:
try {
ViewConfiguration config = ViewConfiguration.get(this);
Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
if (menuKeyField != null) {
menuKeyField.setAccessible(true);
menuKeyField.setBoolean(config, false);
}
} catch (Exception ignored) {
}
Good place to put it would be the onCreate-Method of your Application class.
It will force the App to show the overflow menu. The menu button will still work, but it will open the menu in the top right corner.
[Edit] Since it has come up several times now: This hack only works for the native ActionBar introduced in Android 3.0, not ActionBarSherlock. The latter uses its own internal logic to decide whether to show the overflow menu. If you use ABS, all platforms < 4.0 are handled by ABS and are thus subjected to its logic. The hack will still work for all devices with Android 4.0 or greater (you can safely ignore Android 3.x, since there aren't really any tablets out there with a menu button).
There exists a special ForceOverflow-Theme that will force the menu in ABS, but apperently it is going to be removed in future versions due to complications.
EDIT: Modified to answer for the situation of physical menu button.
This is actually prevented by design. According to the Compatibility Section of the Android Design Guide,
"...the action overflow is available from the menu hardware key. The resulting actions popup... is displayed at the bottom of the screen."
You'll note in the screenshots, phones with a physical menu button don't have an overflow menu in the ActionBar. This avoids ambiguity for the user, essentially having two buttons available to open the exact same menu.
To address the issue of consistency across devices: Ultimately it's more important to the user experience that your app behave consistently with every other app on the same device, than that it behave consistently with itself across all devices.
I use to workaround it by defining my menu like this (also with ActionBarSherlock icon used in my example):
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/menu_overflow"
android:icon="#drawable/abs__ic_menu_moreoverflow_normal_holo_light"
android:orderInCategory="11111"
android:showAsAction="always">
<menu>
<item
android:id="#+id/menu_overflow_item1"
android:showAsAction="never"
android:title="#string/overflow_item1_title"/>
<item
android:id="#+id/menu_overflow_item2"
android:showAsAction="never"
android:title="#string/overflow_item2_title"/>
</menu>
</item>
</menu>
I admit that this may require manual "overflow-management" in your xml, but I found this solution useful.
You can also force device to use HW button to open the overflow menu, in your activity:
private Menu mainMenu;
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// TODO: init menu here...
// then:
mainMenu=menu;
return true;
}
#Override
public boolean onKeyUp(int keycode, KeyEvent e) {
switch(keycode) {
case KeyEvent.KEYCODE_MENU:
if (mainMenu !=null) {
mainMenu.performIdentifierAction(R.id.menu_overflow, 0);
}
}
return super.onKeyUp(keycode, e);
}
:-)
If you are using the action bar from the support library (android.support.v7.app.ActionBar), use the following:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:yorapp="http://schemas.android.com/apk/res-auto" >
<item
android:id="#+id/menu_overflow"
android:icon="#drawable/icon"
yourapp:showAsAction="always"
android:title="">
<menu>
<item
android:id="#+id/item1"
android:title="item1"/>
<item
android:id="#+id/item2"
android:title="item2"/>
</menu>
</item>
</menu>
This kind of method is prevented by the Android Developers Design System, but I found a way to pass it:
Add this to your XML menu file:
<item android:id="#+id/pick_action_provider"
android:showAsAction="always"
android:title="More"
android:icon="#drawable/ic_action_overflow"
android:actionProviderClass="com.example.AppPickActionProvider" />
Next, create a class named 'AppPickActionProvider', and copy the following code to it:
package com.example;
import android.content.Context;
import android.util.Log;
import android.view.ActionProvider;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.SubMenu;
import android.view.View;
public class AppPickActionProvider extends ActionProvider implements
OnMenuItemClickListener {
static final int LIST_LENGTH = 3;
Context mContext;
public AppPickActionProvider(Context context) {
super(context);
mContext = context;
}
#Override
public View onCreateActionView() {
Log.d(this.getClass().getSimpleName(), "onCreateActionView");
return null;
}
#Override
public boolean onPerformDefaultAction() {
Log.d(this.getClass().getSimpleName(), "onPerformDefaultAction");
return super.onPerformDefaultAction();
}
#Override
public boolean hasSubMenu() {
Log.d(this.getClass().getSimpleName(), "hasSubMenu");
return true;
}
#Override
public void onPrepareSubMenu(SubMenu subMenu) {
Log.d(this.getClass().getSimpleName(), "onPrepareSubMenu");
subMenu.clear();
subMenu.add(0, 1, 1, "Item1")
.setIcon(R.drawable.ic_action_home).setOnMenuItemClickListener(this);
subMenu.add(0, 2, 1, "Item2")
.setIcon(R.drawable.ic_action_downloads).setOnMenuItemClickListener(this);
}
#Override
public boolean onMenuItemClick(MenuItem item) {
switch(item.getItemId())
{
case 1:
// What will happen when the user presses the first menu item ( 'Item1' )
break;
case 2:
// What will happen when the user presses the second menu item ( 'Item2' )
break;
}
return true;
}
}
Well I think that Alexander Lucas has provided the (unfortunately) correct answer so I'm marking it as the "correct" one. The alternative answer I'm adding here is simply to point any new readers to this post in the Android Developers blog as a rather complete discussion of the topic with some specific suggestions as to how to deal with your code when transitioning from pre-level 11 to the new Action Bar.
I still believe it was a design mistake not have the menu button behave as a redundant "Action Overflow" button in menu button enabled devices as a better way to transition the user experience but its water under the bridge at this point.
I'm not sure if this is what you're looking for, but I built a Submenu within the ActionBar's Menu and set its icon to match the Overflow Menu's Icon. Although it wont have items automatically sent to it, (IE you have to choose what's always visible and what's always overflowed) it seems to me that this approach may help you.
In the gmail app that comes with ICS pre-installed, the menu button is disabled when you have multiple items selected. The overflow menu is here "forced" to be triggered by the use of the overflow button instead of the physical menu button. Theres a 3rd-party lib called ActionBarSherlock which lets you "force" the overflow menu. But this will only work on API level 14 or lower(pre-ICS)
If you use Toolbar, you can show the overflow on all versions and all devices, I've tried on some 2.x devices, it works.
Sorry if this problem is dead.
Here is what I did to resolve the error. I went to layouts and created two ones containing toolbars. One was a layout for sdk version 8 and the other was for sdk version 21. On version 8, I used the android.support.v7.widget.Toolbar while I used android.widget.Toolbar on the sdk 21 layout.
Then I inflate the toolbar in my activity. I check the sdk to see if it was 21 or higher. I then inflate the corresponding layout. This forces the hardware button to map onto the toolbar you actually designed.
For anyone using the new Toolbar:
private Toolbar mToolbar;
#Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
...
}
#Override
public boolean onKeyUp(int keycode, KeyEvent e) {
switch(keycode) {
case KeyEvent.KEYCODE_MENU:
mToolbar.showOverflowMenu();
return true;
}
return super.onKeyUp(keycode, e);
}
I've been away from Java for some time --functional programming has been my muse-- and recently decided to jump back in with an android application. Things are going well. Javas syntax is mostly back in my brain, OO design principles are a little rusty, but I'm not afraid of re-factoring.
One problem I hit has been with the option menus in the platform. I load them from an XML file through a menu-inflator in my main activity (below), and I can see them! But, when I press them things get weird --but not like seeing your grandmother make-out with your best friend, much less weird.
For some reason, when I press the first button, I get the friendly default message in the code sample below, "That's not an option, moron!". And when I press the second, the message is "Adding One". I'm off by one somehow! But, but how!? but why!?
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/add_single_id"
android:title="#string/add_one" />
<item android:id="#+id/add_multi_id"
android:title="#string/add_multi" />
</menu>
... which is loaded by the menu inflator...
public boolean onCreateOptionsMenu( Menu menu ){
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.option_menu, menu);
return true;
}
... and finally the listener for items selected.
public boolean onOptionsItemSelected( MenuItem item ){
switch( item.getItemId() ){
case R.id.add_single_id:
Toast.makeText(this, "Adding One", Toast.LENGTH_LONG).show();
add_single();
break;
case R.id.add_multi_id:
Toast.makeText(this, "Adding n", Toast.LENGTH_LONG).show();
Intent i = new Intent(this, SelectMulti.class);
startActivityForResult(i, ACTIVITY_LOADMULTI);
break;
default:
Toast.makeText(this, "That's not an option, moron!", Toast.LENGTH_LONG).show();
return false;
}
return true;
}
This happen to me many times when I am developing android on eclipse, and clean and rebuilding a project fixes it as it will recreate android Resource file and correctly map to your UI id's.
In your XML you have ID = add_one_id but in the code you use R.id.add_single_id