In my application I do
Uri webAddress = Uri.parse("http://www.nrk.no");
Intent webIntent = new Intent(Intent.ACTION_WEB_SEARCH, webAddress);
String title = "Choose an app";
Intent chooserIntent = Intent.createChooser(webIntent, title);
startActivity(chooserIntent);
But the chooser that pops open says that No apps can perform this action. What am I doing wrong?
EDIT: Changing to ACTION_VIEW made it work, why?
I haven't used ACTION_WEB_SEARCH but it looks like the difference is what action it actually takes. You aren't providing a query to search for so the appropriate action would be ACTION_VIEW.
Take a look here in the docs. You could provide a query in the Intent.EXTRAS and see if that allows you to use ACTION_WEB_SEARCH
Related
I would like to share a URI from my app, and have the app chooser dialog show options for ACTION_SEND apps (like SMS and copy to clipboard) as well as ACTION_VIEW apps (like Chrome). So far, I can only seem to get one set of apps to show at a time. Is there a way to combine intent actions?
Here is what plain ACTION_SEND intent looks like:
Intent i = new Intent();
i.setAction(Intent.ACTION_SEND);
i.setType("text/plain");
i.putExtra(Intent.EXTRA_TEXT, "www.example.com");
context.startActivity(Intent.createChooser(i, "Share"));
This results in the normal chooser for apps that send information. But no open in browser options.
Here is what ACTION_VIEW intent looks like:
Intent i = new Intent();
i.setAction(Intent.ACTION_VIEW);
i.putData(Uri.parse("www.example.com"))
context.startActivity(Intent.createChooser(i, "Share"));
This results in the normal chooser for opening the link in the browser. But no options for info sending apps.
Is there a way to "combine" these two behaviors so both sets of options show up in the chooser dialog?
I have also tried to add categories to the intent, but no luck.
EDIT: I stumbled across this question where the OP has the same issue. However, I would like a solution that does not involve creating a bunch of custom activities for each app I'd like to show in the chooser.
I know this is late, but have a different solution:
Create intents for send and view. Create a chooser intent for one of them and pass the other intent as Intent.EXTRA_INITIAL_INTENTS. Like this:
// Share
val sendIntent = Intent(Intent.ACTION_SEND)
sendIntent.setDataAndType(uri, MIME_PDF_TYPE)
sendIntent.putExtra(Intent.EXTRA_TEXT, "TEST")
sendIntent.putExtra(Intent.EXTRA_STREA, uri)
// Open
val openIntent = Intent(Intent.ACTION_VIEW)
openIntent.setDataAndType(uri, MIME_PDF_TYPE)
openIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
val chooserIntent = Intent.createChooser(sendIntent,activity.getString(R.string.sharing_title))
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, arrayOf(openIntent))
activity.startActivity(chooserIntent)
i have kotlin snippet and i'm sharing with you. You can use sharecompact builder.
ShareCompat.IntentBuilder.from(requireActivity())
.setType("text/plain")
.setSubject(getString(R.string.app_name))
.setChooserTitle("Share via")
.setText(your text)
.startChooser()
Background
In my Android App, users can share generated images to other apps. It's working nicely using the ACTION_SEND Intent.
Many users have asked why they can't share to Instagram stories directly.
Initially I thought Instagram doesn't support receiving Intents for stories (correct to some extent). I searched for it today, and according to this documentation, to share to Instagram Stories, a separate intent com.instagram.share.ADD_TO_STORY has to be used. I tried it, and it works fine.
The problem:
How do I keep both the options available?
I thought about it a lot, and came up with the following options:
1) Have two separate buttons. It will work, but it will look/feel bad.
2) Have my app accept ACTION_SEND intent, name it as Share to Instagram Story, and redirect the intent to the com.instagram.share.ADD_TO_STORY intent. In principle, make a proxy intent.
It will work, and look/feel great, but I don't know if its allowed (legal, etc) and can I disable the intent if the user doesn't have Instagram installed.
3) Add the 'com.instagram.share.ADD_TO_STORY' to the app chooser launched by ACTION_SEND. This would be ideal, but I don't know how to do it.
If you want to add multiple actions to Intent and create a chooser look at this example:
Intent viewIntent = new Intent(Intent.ACTION_VIEW);
Intent editIntent = new Intent(Intent.ACTION_EDIT);
viewIntent.setDataAndType(uri, type);
editIntent.setDataAndType(uri, type);
Intent chooserIntent = Intent.createChooser(editIntent, "Open in...");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] { viewIntent });
startActivity(chooserIntent);
UPDATE: Here is good solution to your answer. How to make an intent with multiple actions
I tried the same approach as on Facebook's official documentation then tested on Huawai P9 Lite, Huawai P20 Lite and on Samsung S8 - it only worked on Samsung S8 for not known reason (to me). I gave up on it since, obviously, it's not working on most of the phones.
// Define image asset URI
Uri stickerAssetUri = Uri.parse("your-image-asset-uri-goes-here");
String sourceApplication = "com.my.app";
// Instantiate implicit intent with ADD_TO_STORY action,
// sticker asset, and background colors
Intent intent = new Intent("com.instagram.share.ADD_TO_STORY");
intent.putExtra("source_application", sourceApplication);
intent.setType(MEDIA_TYPE_JPEG);
intent.putExtra("interactive_asset_uri", stickerAssetUri);
intent.putExtra("top_background_color", "#33FF33");
intent.putExtra("bottom_background_color", "#FF00FF");
// Instantiate activity and verify it will resolve implicit intent
Activity activity = getActivity();
activity.grantUriPermission("com.instagram.android", stickerAssetUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
if (activity.getPackageManager().resolveActivity(intent, 0) != null) { activity.startActivityForResult(intent, 0);}
My app forwards users to a different app to perform a specific action (e.g. ACTION_SHARE, except that the apps that I forward users to do not implement an intent filter) Since they don't implement intent filters, I have a list of package names that support the action.
This part is working fine, like this:
for (String knownApp : knownApps) {
Intent intent = pm.getLaunchIntentForPackage(knownApp);
if (intent != null) {
ResolveInfo resolveInfo = pm.resolveActivity(intent, 0);
intentList.add(new LabeledIntent(intent, knownApp, resolveInfo.loadLabel(pm), resolveInfo.icon));
}
}
LabeledIntent[] extraIntents = intentList.toArray(new LabeledIntent[intentList.size()]);
Intent openInChooser = Intent.createChooser(actionIntent, getString(R.string.perform_action_with));
openInChooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents);
startActivity(openInChooser);
If the user has none of the apps installed, I want to give the user a choice of apps to download to fulfill the action.
Currently that looks like this.
As you can see it's lacking both icon and name. For regular apps I use an intent chooser which needs LabledIntent, but on one hand, I can't get the name and icon from the playstore unless I scrape them (which is not allowed by google, besides LabledIntent requires a resourceId as the Icon, which I can't get for downloaded files.), on the other the intent chooser won't seem to display the intent unless the package name of the intent and LabeledIntent match. This does not work for URIs which I'm using to access the Play Store in the first place.
Now I'm looking for ideas on how to get the following code to display both the correct name and app icon, as well as forward to the correct page on the play store.
protected void showPlayStoreOptions(List<String> knownApps) {
Intent chooserIntent = new Intent();
Intent showIntent = Intent.createChooser(chooserIntent, "You need one of these Apps on Google Play..."); //googles brand guidelines state that "on Google Play" has to be used
List<Intent> list = new ArrayList<>();
for (String knownApp : knownApps) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + knownApp)); //normally you would try an uri with market:// first, catch the exception if no playstore is installed and then use this, but the intent chooser seems to automatically forward correctly.
list.add(intent);
//list.add(new LabeledIntent(intent, "https://play.google.com/store/apps/details?id=" + knownApp, "test name", R.drawable.icon_info));
//list.add(new LabeledIntent(intent, ""+Uri.parse("https://play.google.com/store/apps/details?id=" + knownApp), "test name", R.drawable.icon_info));
}
showIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, list.toArray(new Intent[list.size()]));
startActivity(showIntent);
}
So to sum up my questions.
How can I get a resource Id from a downloaded image file, or how can I use the downloaded image file with a LabledIntent.
(Extending LabledIntent does not work due to issues with parceling (and those methods are package private))
How can I display a LabledIntent in a choose intent with an URI?
I realize it's probably easier to write my own chooser, but I want to wrangle this into the default android system.
I am using this tutorial to learn about the basics of Intents in Android. The code sample I am using is adopted from the section named "Force an App Chooser" on the page linked.
The following is the method which should be invoked on the click of the button.
public void startSecondActivity(View view) {
Intent intent = new Intent(Intent.ACTION_SEND);
String fileChooserLabel = getResources().getString(R.string.fileChooserLabel);
Intent fileChooserIntent = Intent.createChooser(intent, fileChooserLabel);
if (intent.resolveActivity(getPackageManager())!=null) {
startActivity(intent);
} else {
textView = (TextView) findViewById(R.id.text_view);
textView.setText("False");
}
}
But it just enters the else block of the if-else conditional. I tried this app on both a real device and the emulator. So can anybody point out what might be wrong here, and what I can do about it.
Note: I did not add anything to the Manifest file, since I am using Eclipse IDE and I suppose whatever is required at this point is automatically added to the manifest file.
It is returning null because there are no activities on the device that support your Intent. In this case, your ACTION_SEND Intent is not properly set up.
Note that the code sample you used as a reference is not a tutorial. It is not designed to be a complete code sample. In fact, what they list there will not even compile, as their ... is meant to be replaced by your own code to complete setting up the Intent.
You will need to fully configure your ACTION_SEND Intent, most notably setting the MIME type, as is covered elsewhere in the documentation. Replacing:
Intent intent = new Intent(Intent.ACTION_SEND);
with something like:
Intent intent = new Intent(Intent.ACTION_SEND)
.setType("text/plain")
.putExtra(Intent.EXTRA_TEXT, "IM IN UR STAK OVERFLO ANZWR");
should suffice.
Is it possible to show a list of applications (with intent.createChooser) that only show me my twitter apps on my phone (so htc peep (htc hero) or twitdroid). I have tried it with intent.settype("application/twitter") but it doesnt find any apps for twitter and only shows my mail apps.
Thank you,
Wouter
I'm posting this because I haven't seen a solution yet that does exactly what I want.
This primarily launches the official Twitter app, or if that is not installed, either brings up a "Complete action using..." dialog (like this) or directly launches a web browser.
For list of different parameters in the twitter.com URL, see the Tweet Button docs.
Remember to URL encode the parameter values. (This code is specifically for tweeting a URL; if you don't want that, just leave out the url param.)
// Create intent using ACTION_VIEW and a normal Twitter url:
String tweetUrl = String.format("https://twitter.com/intent/tweet?text=%s&url=%s",
urlEncode("Tweet text"),
urlEncode("https://www.google.fi/"));
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(tweetUrl));
// Narrow down to official Twitter app, if available:
List<ResolveInfo> matches = getPackageManager().queryIntentActivities(intent, 0);
for (ResolveInfo info : matches) {
if (info.activityInfo.packageName.toLowerCase().startsWith("com.twitter")) {
intent.setPackage(info.activityInfo.packageName);
}
}
startActivity(intent);
(URL encoding is cleaner if you have a little utility like this somewhere, e.g. "StringUtils".)
public static String urlEncode(String s) {
try {
return URLEncoder.encode(s, "UTF-8");
}
catch (UnsupportedEncodingException e) {
Log.wtf(TAG, "UTF-8 should always be supported", e);
throw new RuntimeException("URLEncoder.encode() failed for " + s);
}
}
For example, on my Nexus 7 device, this directly opens the official Twitter app:
If official Twitter app is not installed and user either selects Chrome or it opens automatically (as the only app which can handle the intent):
The solutions posted before, allow you to post directly on your first twitter app. To show a list of twitters app (if there are more then one), you can custom your Intent.createChooser to show only the Itents you want.
The trick is add EXTRA_INITIAL_INTENTS to the default list, generated from the createChoose, and remove the others Intents from the list.
Look at this sample where I create a chooser that shows only my e-mails apps. In my case appears three mails: Gmail, YahooMail and the default Mail.
private void share(String nameApp, String imagePath) {
List<Intent> targetedShareIntents = new ArrayList<Intent>();
Intent share = new Intent(android.content.Intent.ACTION_SEND);
share.setType("image/jpeg");
List<ResolveInfo> resInfo = getPackageManager().queryIntentActivities(share, 0);
if (!resInfo.isEmpty()){
for (ResolveInfo info : resInfo) {
Intent targetedShare = new Intent(android.content.Intent.ACTION_SEND);
targetedShare.setType("image/jpeg"); // put here your mime type
if (info.activityInfo.packageName.toLowerCase().contains(nameApp) ||
info.activityInfo.name.toLowerCase().contains(nameApp)) {
targetedShare.putExtra(Intent.EXTRA_TEXT, "My body of post/email");
targetedShare.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(imagePath)) );
targetedShare.setPackage(info.activityInfo.packageName);
targetedShareIntents.add(targetedShare);
}
}
Intent chooserIntent = Intent.createChooser(targetedShareIntents.remove(0), "Select app to share");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[]{}));
startActivity(chooserIntent);
}
}
You can run like that: share("twi", "/sdcard/dcim/Camera/photo.jpg");
This was based on post: Custom filtering of intent chooser based on installed Android package name
This question is a bit older, but since I have just come across a similar problem, it may also still be of interest to others. First, as mentioned by Peter, create your intent:
Intent tweetIntent = new Intent(Intent.ACTION_SEND);
tweetIntent.putExtra(Intent.EXTRA_TEXT, "Test; please ignore");
tweetIntent.setType("application/twitter");
"application/twitter" is in fact a known content type, see here. Now, when you try to start an activity with this intent, it will show all sorts of apps that are not really Twitter clients, but want a piece of the action. As already mentioned in a couple of the "why do you even want to do that?" sort of answers, some users may find that useful. On the other hand, if I have a button in my app that says "Tweet this!", the user would very much expect this to bring up a Twitter client.
Which means that instead of just launching an activity, we need to filter out the ones that are appropriate:
PackageManager pm = getPackageManager();
List<ResolveInfo> lract
= pm.queryIntentActivities(tweetIntent,
PackageManager.MATCH_DEFAULT_ONLY);
boolean resolved = false;
for(ResolveInfo ri: lract)
{
if(ri.activityInfo.name.endsWith(".SendTweet"))
{
tweetIntent.setClassName(ri.activityInfo.packageName,
ri.activityInfo.name);
resolved = true;
break;
}
}
You would need to experiment a bit with the different providers, but if the name ends in ".SendTweet" you are pretty safe (this is the activity name in Twidroyd). You can also check your debugger for package names you want to use and adjust the string comparison accordingly (i.e. Twidroyd uses "com.twidroid.*").
In this simple example we just pick the first matching activity that we find. This brings up the Twitter client directly, without the user having to make any choices. If there are no proper Twitter clients, we revert to the standard activity chooser:
startActivity(resolved ? tweetIntent :
Intent.createChooser(tweetIntent, "Choose one"));
You could expand the code and take into account the case that there is more than one Twitter client, when you may want to create your own chooser dialog from all the activity names you find.
It is entirely possible your users will only ever, now and forever, only want to post to Twitter.
I would think that it is more likely that your users want to send information to people, and Twitter is one possibility. But, they might also want to send a text message, or an email, etc.
In that case, use ACTION_SEND, as described here. Twidroid, notably, supports ACTION_SEND, so it will appear in the list of available delivery mechanisms.
These answers are all overly complex.
If you just do a normal url Intent that does to Twitter.com, you'll get this screen:
which gives you the option of going to the website if you have no Twitter apps installed.
String url = "https://twitter.com/intent/tweet?source=webclient&text=TWEET+THIS!";
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
startActivity(i);
Either
You start an activity with an Intent with action Intent.ACTION_SEND and the text/plain MIME type. You'll have all applications that support sending text. That should be any twitter client, as well as Gmail, dropbox, etc.
Or, you try to look up for the specific action of every client you are aware of, like "com.twitter.android.PostActivity" for the official client. That will point to this client, and that is unlikely to be a complete list.
Or, you start with the second point, and fall back on the first...
Nope. The intent type is something like image/png or application/pdf, i.e. a file type, and with createChooser you're basically asking which apps can open this file type.
Now, there's no such thing as an application/twitter file that can be opened, so that won't work. I'm not aware of any other way you can achieve what you want either.
From http://twidroid.com/plugins/
Twidroid’s ACTION_SEND intent
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is a sample message via Public Intent");
sendIntent.setType("application/twitter");
startActivity(Intent.createChooser(sendIntent, null));
I used "billynomates" answer and was able to use hashtags by using the "URLEncoder.encode(, "UTF-8")" function. The hash tags showed up just fine.
String originalMessage = "some message #MESSAGE";
String originalMessageEscaped = null;
try {
originalMessageEscaped = String.format(
"https://twitter.com/intent/tweet?source=webclient&text=%s",
URLEncoder.encode(originalMessage, "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
if(originalMessageEscaped != null) {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(originalMessageEscaped));
startActivity(i);
}
else {
// Some Error
}