Android error java.lang.NoSuchMethodError: android.view.MenuItem.getActionProvider - android

I enabled the ShareActionProvider and I get this error:
java.lang.NoSuchMethodError: android.view.MenuItem.getActionProvider
But the way I use this class is like this:
// SHARING ONLY ENABLED in SDK 14 which is Ice Cream Sandwich
try
{
if ( android.os.Build.VERSION.SDK_INT >= 14 )
{
Button share = (Button)findViewById(R.id.share_button);
share.setOnClickListener(new Button.OnClickListener()
{
public void onClick(View v)
{
openOptionsMenu();
}
});
}
else
{
// HIDE THE TWO PAGE ELEMENTS
Button share = (Button)findViewById(R.id.share_button);
TextView share_prompt = (TextView)findViewById(R.id.share_prompt);
share.setVisibility(View.GONE);
share_prompt.setVisibility(View.GONE);
}
}
catch ( Exception e )
{
}
So I thought that I would not show the share button for earlier sdk's and I would be ok. But I am getting a lot of crashes.
I can not really test this because I don't have a phone with an earlier version of the SDK. But does it mean that these pages crash for everyone who has the earlier SDK version? Or just people who click share? How do I prevent this crashing?
And I have these methods in the class. Should I just not run them if sdk is less than 14?
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.layout.menu, menu);
MenuItem item = menu.findItem(R.id.menu_item_share);
myShareActionProvider = (ShareActionProvider)item.getActionProvider();
myShareActionProvider.setShareHistoryFileName(
ShareActionProvider.DEFAULT_SHARE_HISTORY_FILE_NAME);
myShareActionProvider.setShareIntent(createShareIntent());
return true;
}
private Intent createShareIntent()
{
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT,
"Some text");
return shareIntent;
}
// Somewhere in the application.
public void doShare(Intent shareIntent)
{
// When you want to share set the share intent.
myShareActionProvider.setShareIntent(shareIntent);
}
Thanks.
Alex

ShareActionProvider is available only for API 14+ which means in earlier versions you can't use it. If you want to add share button in your app and support old API levels I can suggest you to use ActionBarSherlock - a library which gives you the opportunity to use ActionBar in older versions of Android. Using this library you can do something like this to add share button :
MenuItem actionItem = menu.findItem(R.id.menu_item_share_action_provider_action_bar);
ShareActionProvider actionProvider = (ShareActionProvider) actionItem.getActionProvider();
actionProvider.setShareHistoryFileName(ShareActionProvider.DEFAULT_SHARE_HISTORY_FILE_NAME);
actionProvider.setShareIntent(createShareIntent());
private Intent createShareIntent() {
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("image/*");
Uri uri = Uri.fromFile(getFileStreamPath("shared.png"));
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
return shareIntent;
}
Which will share an image file. If you don't want to support older API levels I would suggest you just check for API level and depending on that use ShareActionProvider.
Hope this help.

Yes, you need to have those same checks for your menu items. See the docs for getActionProvider. It's only supported on 14+. To test this kind of thing without a device, you can try on an emulator that uses an older version of Android.

In documentation you can see that MenuItem.getActionProvifer() from 14 API, of course you will catch java.lang.NoSuchMethodError on older versions (that errors you will catch every time when use methods or classes from new API).
Using try-catch can't save you:) You need to use different implementations with workarounds hanler-classes for different critical API versions.
If you will use ActionBarSherlock, you can use that method in Android API >= 8. Try to save functional for maximem API, it will be great!

A little late....
ShareActionProvider and in general ActionProviders are added from Android 4.0 (API Level 14) to Android Framework.
But the AndroidSupportLibrary helps us to support this feature in previous versions as well. But generally we do a mistake importing the ShareActionProvider from the Android SDK framework but not the SupportLibrary.
CODE:
-->In the 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/menu_share" android:title="#string/menuitem_detail_share"
app:showAsAction="always"
app:actionProviderClass="android.support.v7.widget.ShareActionProvider" />
</menu>
Note: Observe that the 'app' namespace is used and not 'android' namespace'
WHY? => This is necessary when using any XML attributes defined by the support library, because these attributes do not exist in the Android framework on older devices. So you must use your own namespace as a prefix for all attributes defined by the support library.
-->In the Activity's onCreateOptionsMenu() :
ShareActionProvider mShareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(menuItem);
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT, "The Text you want to share);
mShareActionProvider.setShareIntent(shareIntent);
Note: ShareActionProvider is imported from "import android.support.v7.widget.ShareActionProvider" and observe the usage of "MenuItemCompat.getActionProvider()" to get the ActionProvider instance.

You need to add condition to your when you support lower APIs while still using higher API calls. IT will fail in such case as there's simply no such method yet. And I'd suggest to slightly improve readability for your code, by replacing lines like:
if ( android.os.Build.VERSION.SDK_INT >= 14 )
with
if ( android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWITCH )

Related

Size of ShareAction icon issue on ActionBar with ShareActionProvider-v7

I was working around my old ShareAction on my ActionBar and it was working since I updated my Packages on SDK Manager. I saw this doc from Google which says,
To add a "share" action to your activity, put a ShareActionProvider in
the app bar's menu resource. For example:
And I've added the same without adding any Icons:
<item android:id="#+id/action_share"
android:title="#string/share"
app:showAsAction="ifRoom"
app:actionProviderClass="android.support.v7.widget.ShareActionProvider"/>
I was using:
app:actionProviderClass="Mypackagename.ShareActionProvider"
With a custom ShareActionProvider with the following code.you can see it here.
I saw a hack or a trick to do that (with ShareActionProvider-v4) and everything was good since I decided to use android.support.v7.widget.ShareActionProvider.
So, Here is my currently code:
<item
android:id="#+id/shareac"
android:title="#string/share"
app:actionProviderClass="android.support.v7.widget.ShareActionProvider"
app:showAsAction="always" />
I didn't use the Icon because here the doc says,
You do not need to specify an icon, since the ShareActionProvider
widget takes care of its own appearance and behavior. However, you do
need to specify a title with android:title, in case the action ends up
in the overflow menu.
And here is what I've done so far:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main_details, menu);
// Locate MenuItem with ShareActionProvider
MenuItem item = menu.findItem(R.id.shareac);
// Fetch and store ShareActionProvider
mShareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(item);
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
Bundle extra = getIntent().getExtras();
String title = extra.getString("title");
Bundle extraurl = getIntent().getExtras();
String url = extraurl.getString("url");
shareIntent.putExtra(Intent.EXTRA_TEXT, "Check this new project from something : " + title + url);
shareIntent.setType("text/plain");
mShareActionProvider.setShareIntent(shareIntent);
return true;
}
So, here what I see right now in Android Studio 1.5.1 Is,
And if run and compile the app:
As you can see, the size of ShareAction is too much. (It's violating the MaterialDesign guideline I guess).
I forgot to say, I've already tried android:icon="#mipmap/ic_share" which that was working with my previous method/trick. But, check this Preview from AndroidStudio:
And here is after compiled:
Nothing changed!
So, my question: is that a bug or what am I doing wrong here?
Intent.createChooser didn't work also: from: https://stackoverflow.com/a/34797718/4409113
Edit:
The most interesting part, i just saw the same design and the same resutls from Google on the following course and on that app which they've called it SunShine app:
Applink
Course:
https://www.udacity.com//course/viewer#!/c-ud855/l-3961788738/m-4294896397
Okay, As ianhanniballake at this post said,
Icons in material design are 24dp x 24dp, as properly reflected by the
SearchView. However, ShareActionProvider has not yet been updated to
material design by default.
By the way, i've just posted a question/report to code.google.com which you can see it here:
http://code.google.com/p/android/issues/detail?id=200335
It seems that default icon is 24dp x 24dp but it should be like this:
But now, it is like this:
Seems to be a bug and still waiting for accepting or answering about it.I'll update this post if they answered.7 days passed!
UPDATE:
Finally, they've assigned the defect on to the development team and they will update this issue with more information as it becomes available.
Big thanks to ssingamc...#google.com at Google for support.
The answer is available here: http://code.google.com/p/android/issues/detail?id=200335#c10
I will update this answer if any updates or any fixes was available.
UPDATE: http://code.google.com/p/android/issues/detail?id=200335#c12
Hi, The development team has fixed the issue that you have reported
and it will be available in a future build. Thanks
Icons in material design are 24dp x 24dp, as properly reflected by the SearchView. However, ShareActionProvider has not yet been updated to material design by default.
You can set actionModeShareDrawable in your theme to set the share icon in the ShareActionProvider:
<item name="actionModeShareDrawable">#drawable/share_icon</item>
Note that ShareActionProvider is not found anywhere in the material design guidelines and with Android M's Direct Share capability (which requires you use a standard share intent at this time), it is unclear on whether the ShareActionProvider is a suggested pattern any more.
For more detail Visit Here.
AppCompat ShareActionProvider icon is too big compared to other icons
Change the icon Pragmatically
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main_details, menu);
// Locate MenuItem with ShareActionProvider
MenuItem item = menu.findItem(R.id.shareac);
// Fetch and store ShareActionProvider
mShareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(item);
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
Bundle extra = getIntent().getExtras();
String title = extra.getString("title");
Bundle extraurl = getIntent().getExtras();
String url = extraurl.getString("url");
shareIntent.putExtra(Intent.EXTRA_TEXT, "Check this new project from something : " + title + url);
shareIntent.setType("text/plain");
mShareActionProvider.setShareIntent(shareIntent);
//Here
item.setIcon(getResources().getDrawable(R.drawable.ic_share));
return true;
}
or Theme
<item name="actionModeShareDrawable">#drawable/ic_share</item>
If you don't need custom icon for share menu item then try android resource for share menuitem as below:
<item android:id="#+id/action_share"
android:title="#string/share"
app:showAsAction="ifRoom"
android:icon="#android:drawable/ic_share"
app:actionProviderClass="android.support.v7.widget.ShareActionProvider"/>
See here

How to disable api level check for a specific code snippet

How to disable api level check for a specific code line that is giving the following error:
Call requires API level 14 (current min is 11): android.view.MenuItem#getActionProvider
this is the where it is giving the error getActionProvider
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_server_status, menu);
MenuItem item = menu.findItem(R.id.menu_item_share);
if(android.os.Build.VERSION.SDK_INT >= 14) {
mShareActionProvider = (ShareActionProvider) item.getActionProvider();
// Create the share Intent
String playStoreLink = "https://play.google.com/store/apps/details?id=" +
getPackageName();
String yourShareText = "Install this app " + playStoreLink;
Intent shareIntent = ShareCompat.IntentBuilder.from(this)
.setType("text/plain").setText(yourShareText).getIntent();
// Set the share Intent
mShareActionProvider.setShareIntent(shareIntent);
}
return true;
}
this is a menu that should work for all APIs 11+, if it is 14+ then the share button should work normally else i will hide that button from the menu or even load another menu.
I tried using #TargetApi but when I did that i tried to create another onCreateOptionsMenu but that is not possible to create two functions with the same name even when I used the #TargetApi
Even better is there a share button that works with API 11+?
I tried using #TargetApi
That is the right answer.
when I did that i tried to create another onCreateOptionsMenu
You do not need another onCreateOptionsMenu() method.
Even better is there a share button that works with API 11+?
android.widget.ShareActionProvider works on API Level 14+. android.support.v4.view.ShareActionProvider works on API Level 4+, if are using the AppCompat action bar backport.
Note that there are virtually no devices running API Level 11-13, so worrying about 11 is not especially relevant today.

ActivityOptionsCompat not working in android 2.3

I have implemented window animations using ActivityOptionsCompat and ActivityCompat which is recently supported in android support-v4 library.
I have used below code for implement animation:
Intent subActivity = new Intent(WindowAnimations.this,
AnimatedSubActivity.class);
// The enter/exit animations for the two activities are
// specified by xml resources
Bundle translateBundle = ActivityOptionsCompat
.makeCustomAnimation(WindowAnimations.this,
R.anim.slide_in_left, R.anim.slide_out_left)
.toBundle();
ActivityCompat.startActivity(WindowAnimations.this,
subActivity, translateBundle);
Above code is working fine in android 4.3 and 4.0.
Anybody able to make it work in 2.X?Any help is appreciated.
#Luksprog basically already answered this in the first on your question, but here's some more documentation to further support that claim.
First, read the the javadoc for ActivityCompat#startActivity(Activity activity, Intent intent, Bundle options) carefully. I've highlighted some relevant keywords:
Start an activity with additional launch information, if able.
In Android 4.1+ additional options were introduced to allow for more
control on activity launch animations. Applications can use this
method along with ActivityOptionsCompat to use these animations when
available. When run on versions of the platform where this feature
does not exist the activity will be launched normally.
So that basically tells us that the (optional) animations feature will only work on versions of Android that natively support it. On all other platform versions, the Activity will be launched 'normally' - that is, without the optional animation.
The actual proof can easily be found in the source code of ActivityCompat:
public static void startActivity(Activity activity, Intent intent, Bundle options) {
if (Build.VERSION.SDK_INT >= 16) {
ActivityCompatJB.startActivity(activity, intent, options);
} else {
activity.startActivity(intent);
}
}
In other words: if this code is executed on a pre-JB device, a plain old startActivity() call will be mad, where the options parameter gets ignored. Only JB devices will end up using that.
Perhaps redundant to mention, but obviously the same applies to the startActivityForResult() counterpart.
To summarize: Currently the Support Library simply offers a static helper class to execute certain functionality in "a backwards compatible fashion" - it doesn't actually backport that functionality (yet). All it does at this stage is save you having to write the if/else condition in your own app.
That being said, the current implementation does allow for a future backport of the actual functionality. That's possibly also why the ActivityOptionsCompat class exists. Right now the class provides an 'empty' implementation for pre-JB devices, which, in theory, could be 'filled' at a later stage. Any code calling through these compatibility helpers will then automagically start working.
Example of an ActivityOptionsCompat call returning an empty implementation:
public static ActivityOptionsCompat makeCustomAnimation(Context context,
int enterResId, int exitResId) {
if (Build.VERSION.SDK_INT >= 16) {
return new ActivityOptionsImplJB(
ActivityOptionsCompatJB.makeCustomAnimation(context, enterResId, exitResId));
}
return new ActivityOptionsCompat();
}

Equivalent of NavUtils when not using the Android support library?

This question has also been asked by someone on the Android Developers Google Group (link), but it does not have an answer...
I recently removed the v4 support library from my Android project in Eclipse, because my application only targets Android 4.0 (Ice Cream Sandwich) and up. I'm now going through all the support library references that are giving me errors.
One in particular is NavUtils, which seems to be a support library class used in Activity navigation. Example:
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
What is the equivalent of NavUtils when not using the support library?
Look at the source code of NavUtils, if necessary just copy it to your project. It just gets the parent activity set in the manifest and starts it.
I found #Nikolay's approach to be the best if you don't want to have the whole android v4 support library in your project.
This is the list of classes you should copy into your project:
NavUtils
NavUtilsJB
IntentCompat
IntentCompatHoneycomb
IntentCompatIcsMr1
Android version from Jelly Beans have the NavUtils incorporated into the Activity class.
There is no need to handle the case : android.R.id.home in onOptionsItemSelected().
OR you can just return false for this case in onOptionsItemSelected().
Here is this simplest answer I could find, and what I did in my code:
Simply replace:
NavUtils.navigateUpFromSameTask(this);
with:
navigateUpTo(getParentActivityIntent());
Hope this helps!

Strategies for Honeycomb & backward compatibility

So we've seen the preview sdk and the neat new stuff like ActionBar and Fragments. Making a lot of method calls will be unavoidable to make use of these, so what strategies are there for maintaining 1 version of the app, which will let me use all the snazzy new stuff but also work on devices running 2.3 or below? My app targets 1.5 - 2.3 at the moment.
The same fragment APIs are now available as a static library for use with older versions of Android; it's compatible right back to Android 1.6.
There are a few tricks you can use to see if the various new APIs are available to your app. Generally speaking, you'll probably want to create two alternative sets of Activities, one that uses the fancy new APIs (ActionBar, Animators, etc.) -- and another set that don't.
The following code shows how you can use reflection and exception catching to determine the availability of the Fragment APIs, and version checking to confirm if the other Honeycomb APIs are available.
private static boolean shinyNewAPIsSupported = android.os.Build.VERSION.SDK_INT > 10;
private static boolean fragmentsSupported = false;
private static void checkFragmentsSupported() throws NoClassDefFoundError {
fragmentsSupported = android.app.Fragment.class != null;
}
static {
try {
checkFragmentsSupported();
} catch (NoClassDefFoundError e) {
fragmentsSupported = false;
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent startActivityIntent = null;
if (!shinyNewAPIsSupported)
startActivityIntent = new Intent(this, MainNonActionBarActivity.class);
else
startActivityIntent = new Intent(this, MainActionActivity.class);
startActivity(startActivityIntent);
finish();
}
Generally speaking you can use the same layout definitions. Where Fragments are available you'll inflate each layout within a different Fragment, where they aren't you'll probably want to use <include> tags to embed several of them into a more complex Activity layout.
A more detailed work through of how to write the code to support backwards compatibility on Honeycomb can be found here: http://blog.radioactiveyak.com/2011/02/strategies-for-honeycomb-and-backwards.html
Conveniently, Google's Dianne Hackborne has posted a blog entry covering this exact topic. Google say they'll be providing static libraries so older versions of Android will also be able to use fragments.
You might find Reto Meier's article on backwards-compatibility useful, specifically the section headed "Dealing with missing classes".
I've yet to look at the Honeycomb SDK myself but I, like you, am hoping it's pretty easy and hassle-free to make use the new features without jeopardising compatibility with older devices.
Well google just announced honeycomb will be tablet only: http://www.pcmag.com/article2/0,2817,2379271,00.asp
So if your device is meant for mobile only this may not even be an issue.
Official Android sample that will help you achieve ActionBar from 1.6 to 4.x

Categories

Resources