menu button doesn't show on nexus 7 - android

so I am facing this problem for long time. I've got Nexus 4 and Nexus 7 both running Android 4.3, and i've got application with targetSdkVersion="11"("I use 11 because any target sdk below 11 doesn't support multitouch for me). And the problem is that 3-dot menu shows on Nexus 4 but doesnt show on Nexus 7. 3 dot menu button on nexus 7 works only if I put targetSdkVersion="8" but then multitouch doesnt work
Nexus 4:
Nexus 7 :
code :
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="11" />
screenshots :
nexus 7
nexus 4:

In case you are specifically wondering why the button is not being shown the following rules apply when Android determines if a legacy menu button is needed:
If target API version is less than 11 it is shown on all devices
If target version is 11, 12, or 13 (i.e. tablet-only Honeycomb) Android assumes that your app has been designed for tablets and won't show a legacy button on tablets, but will on phones
If target is 14 or above (ICS and above), Android assumes your app is designed for tablets and phones and so the legacy button isn't shown.
But like the other answers say, you shouldn't be using this menu button. If you don't want an entire ActionBar, another option would to have a three-dot button in your activity which shows a menu using PopupMenu.

You should not be using that menu anymore. From the Menus documentation:
On Android 3.0 and higher, items from the options menu are presented by the action bar as a combination of on-screen action items and overflow options. Beginning with Android 3.0, the Menu button is deprecated (some devices don't have one), so you should migrate toward using the action bar to provide access to actions and other options.
Use an ActionBar.

The correct solution is to use an ActionBar but there may be some hacks to get the overflow menu to appear.
Specifically, there's a hidden window flag FLAG_NEEDS_MENU_KEY you can access via reflection. Here's a code snippet (from this blog):
public static void addLegacyOverflowButton(Window window) {
if (window.peekDecorView() == null) {
throw new RuntimeException("Must call addLegacyOverflowButton() after setContentView()");
}
try {
window.addFlags(WindowManager.LayoutParams.class.getField("FLAG_NEEDS_MENU_KEY").getInt(null));
}
catch (NoSuchFieldException e) {
// Ignore since this field won't exist in most versions of Android
}
catch (IllegalAccessException e) {
Log.w(TAG, "Could not access FLAG_NEEDS_MENU_KEY in addLegacyOverflowButton()", e);
}
}
I tested this on a couple of Nexus devices and it works. Comments on the blog state that there are devices where it doesn't work. Use with caution. And use an ActionBar, really.

There's a simple way to force a menu option to stay in the menu overflow. If you're creating a menu with XML, you can force this using the "showAsAction" attribute.
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/menu_option"
android:showAsAction="never"
android:title="#string/option_name" />
</menu>
If you set "showAsAction" to "never", it will be forced to don't show on the ActionBar, so the option will remain on the menu overflow.
There's more info (like how to vinculate the XML menu file to an Activity) on the official Android documentation webpage: http://developer.android.com/guide/topics/resources/menu-resource.html
I wish this can be helpful!

I wouldnt always recommend using this, since its a hack which breaks the consistency of the phone, but if you want the "3 dots" menu, which is called the overflow menu you need to add this method
//Hack to display overflowMenu on devices with a menu button
private void getOverflowMenu() {
try {
ViewConfiguration config = ViewConfiguration.get(this);
Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
if(menuKeyField != null) {
menuKeyField.setAccessible(true);
menuKeyField.setBoolean(config, false);
}
} catch (Exception e) {
e.printStackTrace();
}
}
And in your onCreate() call this method.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.Activity);
getOverflowMenu();
}

Related

Application crash when pressing the menu button

I am trying to create an app for android and I came across the following problem:
The application crashes in a specific phone when I press the menu button. Let me give you some details first.
The bug occurs to ONLY on LG Optimus L3 II e430 with Android 4.1.2 (tested on four other phones so far)
The application starts with a splash screen and no action bar. At this point menu button just doesn't do anything.
With a simple touch we get past the splash screen and we go to the Main Activity which implements ActionBar activity and has a navigation drawer.
From this point and after, every time I try to click on the menu button the app crashes.
Here is the layout of the menu and the onCreateOptionsMenu function:
res/menu/main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="#+id/action_settings"
android:title="#string/action_settings"
android:orderInCategory="100"
app:showAsAction="never" />
</menu>
Part from MainActivity.java
#Override
public boolean onCreateOptionsMenu(Menu menu) {
if (!mNavigationDrawerFragment.isDrawerOpen()) {
// Only show items in the action bar relevant to this screen
// if the drawer is not showing. Otherwise, let the drawer
// decide what to show in the action bar.
getMenuInflater().inflate(R.menu.main, menu);
restoreActionBar();
return true;
}
return super.onCreateOptionsMenu(menu);
}
Please note that this code is generated from Android Studio.
So far what I've tried:
Tried to look at the file that has the problem from the sdk sources (API Level 16 and 21) but they were not relevant to the stack trace (line shown in the stack trace pointed in a location that didn't make sense).
Tried to install XPosed fix for Google PlayStore crash with menu button bug. Nothing here either.
Found a similar bug report to firefox's bugtracking system so I tried to install Firefox and see if it crashes on my phone when I press Menu Button; firefox didn't crash. (Link to firefox's bug)
Here is the stack trace from LogCat:
10-24 09:08:02.710 4712-4712/com.scaryboxstudios.unrealestateapp E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NullPointerException
at com.android.internal.policy.impl.PhoneWindow.onKeyUpPanel(PhoneWindow.java:1004)
at com.android.internal.policy.impl.PhoneWindow.onKeyUp(PhoneWindow.java:1712)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:2125)
at android.view.ViewRootImpl.deliverKeyEventPostIme(ViewRootImpl.java:3611)
at android.view.ViewRootImpl.handleImeFinishedEvent(ViewRootImpl.java:3581)
at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:2831)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4929)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:798)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:565)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
at dalvik.system.NativeStart.main(Native Method)
Update: With Appcompat-v7 version 22.0.0, onKeyUp does not seem to fire for the Menu key. The original bug appears to be fixed, so I will likely remove the submenu workaround. Unfortunately I haven't verified the fix on an affected LG 4.1 device.
I ended up doing a workaround for this, which users are reporting has fixed the issue for them.
Implement submenus instead of relying on the overflow menu. The caveat to this is that now every device will see the overflow button in the Action Bar even if they have a Menu key.
The following technique is from https://stackoverflow.com/a/18530179/57490
Convert all overflow options menu items to submenus.
Override onKeyUp in your Activities, have it call Menu.performIdentifierAction(R.id.menu_overflow, 0); and do not call super.onKeyUp for keyCode == KEYCODE_MENU.
After stumbling upon the same problem recently I found the root of the problem. The problem is compatibility issues between older and newer support libraries. It seems that I used depreciated stuff around my code together with newer stuff.
I am sorry for being kind of abstract but this question is 4 months old and I cannot remember what exactly were the incorrect lines of code. If memory serves right, the problem lied upon auto generated methods from Android Studio for application drawer activities. I used the Drawer Application project template from Android Studio and I chose to support very old Android APIs too so Android Studio chose the depreciated Android Support Library.
The point is that I resolved the problem when I refactored the code to use non depreciated techniques only.
If you are fighting against a similar problem I strongly recommend remove everything that Android Studio (I assume that you use Android Studio or Eclipse) marks as depreciated.
Also for catching Menu button can use next:
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_MENU) {
// TODO - Your user code
/*
if (event.getAction() == KeyEvent.ACTION_DOWN
&& event.getRepeatCount() == 0) {
// Tell the framework to start tracking this event.
//getKeyDispatcherState().startTracking(event, this);
return true;
} else if (event.getAction() == KeyEvent.ACTION_UP) {
// getKeyDispatcherState().handleUpEvent(event);
if (event.isTracking() && !event.isCanceled()) {
// DO BACK ACTION HERE
return true;
}
}*/
// if you don't want use system listener
// return super.dispatchKeyEvent(event);
return false;
} else {
return super.dispatchKeyEvent(event);
}
}
Worked for lastest AppCompat and SDK version - 22.0

setting button in android application

I develop an android application and put it in a android market. users put comments for me and tell me that setting button doesn't work for my application. I don't know what setting button is and how I can enable it for my application.
can any one help me?
I guess what you mean is the menu button. The problem often is that some devices don't have a physical menu button, thus they cannot access the menu of your app.
Try to use a Holo theme for your app's activities and show an ActionBar. By default, the three dots button for your menu will then be shown in the ActionBar on devices that don't have a physical menu button.
For a consistend UI on all devices, you could show the menu button in your ActionBar permanently, whether the device has a physical menu button or not, using this code:
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
try {
ViewConfiguration config = ViewConfiguration.get(this);
Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
if(menuKeyField != null) {
menuKeyField.setAccessible(true);
menuKeyField.setBoolean(config, false);
}
} catch (Exception e) { e.printStackTrace(); }
}
Do you use Eclipse?
Check if you have a method onCreateOptionsMenu in your activity class.
Eclipse creates automatically this method and adds a menu in your activity (depending on how you create the activity class file)

How to always show Android settings button on ActionBar?

How can I always show Android settings button on ActionBar? (4.0+)
I would like to show it even if the device has an hardware button for settings, so it would be same with devices with and without hardware buttons.
This is what I'm talking about: http://oi48.tinypic.com/2j104l0.jpg
There is one awful hack which generally have been answered on many questions. Call this from your onCreate():
private void getOverflowMenu() {
try {
ViewConfiguration config = ViewConfiguration.get(this);
Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
if(menuKeyField != null) {
menuKeyField.setAccessible(true);
menuKeyField.setBoolean(config, false);
}
} catch (Exception e) {
e.printStackTrace();
}
}
It is highly suggested not to use this hack as sHasPermanentMenuKey field can change anytime. However this has been working for me and others uptil now. See
Android action bar not showing overflow
On a second note, the hardware button is present on the phone for a reason. Just showing the addition overflow menu might confuse your users. Ideally a user would be very much accustomed to using his/her personal phone. So, if the user's phone has a hardware button for overflow menu option, then it need not have the icon on the top of action bar. Having an addition button might confuse users due to difference in behavior in different apps.
Hope that helps.
Edit:
In short, its not recommended as sHasPermanentMenuKey field in the Android code can be changed anytime, which will break your app if not found.

Honeycomb 3.1 / Mono for Android persist 'LightsOut'

I developed my app using Mono for Android. I have the latest version 4.0.3. My AndroidManifest.xml specifies:
<uses-sdk android:targetSdkVersion="11" android:minSdkVersion="8" />
The app runs on tablets, so in Honeycomb I need to hide the status bar at the bottom of the screen. This is how I do that (with a simple extension method):
internal static void LightsOut(this View view)
{
try
{
IntPtr view_setSystemUiVisibility = JNIEnv.GetMethodID(view.Class.Handle, "setSystemUiVisibility", "(I)V");
JNIEnv.CallVoidMethod(view.Handle, view_setSystemUiVisibility, new JValue(1));
}
catch
{ }
}
I call this on every view that I instantiate. On my Motorola Xoom, running 3.0.1, this works great.
On my Samsung Galaxy Tab running 3.1, it works; but the status bar comes back after some short period of time. In the Android Log I see that LightsOn() is getting called...
How can I prevent the status bar from coming back in 3.1? I saw this event:
http://developer.android.com/reference/android/view/View.OnSystemUiVisibilityChangeListener.html
And thought I could use it to hide the status bar, if it comes back. But I don't see how I can subscribe to it (it doesn't show in Intellisense).
Does something specific happen before the status bar comes back, or is it solely time related? A quick search of the ICS source suggests that the status bar status will be reset when the top App Window changes. Are you calling StartActivity() or moving to another app when you see this behavior?
The View.OnSystemUiVisibilityChangeListener interface has been bound as the View.IOnSystemUiVisibilityChangeListener interface and through the View.SystemUiVisibilityChange event. However, both of these mechanisms require that your $(TargetFrameworkVersion) target Android v3.1 or later, which would set your //uses-sdk/#android:minSdkVersion attribute to 12, and is thus something you (presumably) don't want to do.
I see two plausible solutions here:
Figure out why LightsOn() is being invoked and try to work around it (call LightsOut() within every Activity.OnCreate() method?).
Provide two versions of your app, one with a minSdkVersion of 8, and one of (at least) 12, and then use Multiple APK Support to include both in your program. The device will then run the appropriate package, permitting access to the View.SystemUiVisibilityChange event.

How to force use of overflow menu on devices with menu button

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);
}

Categories

Resources