How to force Share Intent to open a specific app? - android

I like share intent, it is perfect to open sharing apps with image and text parameters.
But now i'm researching the way to force share intent to open a specific app from the list, with the paramters given to the share intent.
This is my actual code, it shows the list of sharing apps installed on the phone. Please, can somedone tell me what i should add to the code to force for example official twitter app? and official faccebok app?
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
Uri screenshotUri = Uri.parse("file:///sdcard/test.jpg");
sharingIntent.setType("image/*");
sharingIntent.putExtra(Intent.EXTRA_TEXT, "body text");
sharingIntent.putExtra(Intent.EXTRA_STREAM, screenshotUri);
startActivity(Intent.createChooser(sharingIntent, "Share image using"));
Thanks

For Facebook
public void shareFacebook() {
String fullUrl = "https://m.facebook.com/sharer.php?u=..";
try {
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setClassName("com.facebook.katana",
"com.facebook.katana.ShareLinkActivity");
sharingIntent.putExtra(Intent.EXTRA_TEXT, "your title text");
startActivity(sharingIntent);
} catch (Exception e) {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(fullUrl));
startActivity(i);
}
}
For Twitter.
public void shareTwitter() {
String message = "Your message to post";
try {
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setClassName("com.twitter.android","com.twitter.android.PostActivity");
sharingIntent.putExtra(Intent.EXTRA_TEXT, message);
startActivity(sharingIntent);
} catch (Exception e) {
Log.e("In Exception", "Comes here");
Intent i = new Intent();
i.putExtra(Intent.EXTRA_TEXT, message);
i.setAction(Intent.ACTION_VIEW);
i.setData(Uri.parse("https://mobile.twitter.com/compose/tweet"));
startActivity(i);
}
}

There is a way more generic to do that, and is not necessary to know the full package name of the application intent.
See this post:
How to customize share intent in Android?

100% Working solution
if you want to share something in any app you want or open a url via every action, just use this method:
private void shareOrViewUrlViaThisApp(String appPackageName, String url) {
boolean found = false;
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
List<ResolveInfo> resInfo = getPackageManager().queryIntentActivities(intent, 0);
if (!resInfo.isEmpty()){
for (ResolveInfo info : resInfo) {
if (info.activityInfo.packageName.toLowerCase().contains(appPackageName) ||
info.activityInfo.name.toLowerCase().contains(appPackageName) ) {
intent.setPackage(info.activityInfo.packageName);
found = true;
break;
}
}
if (!found)
return;
startActivity(Intent.createChooser(intent, "Select"));
}
}
and simply call:
shareOrViewUrlViaThisApp(<your package name>,<your url>);
This answer was inspired from this.

Related

Share text to Linkedin using Intent

I am trying to share a text in LinkedIn using the Intent,and i searched a lot and used many codes,but not working..I saw many discussions also but cant find a proper answer for that.
How can i open the LinkedIn to share something through a button click.
I already used the following codes,
if(Utils.doesPackageExist(getSherlockActivity(), "com.linkedin.android"))
{
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setClassName("com.linkedin.android",
"com.linkedin.android.home.UpdateStatusActivity");
shareIntent.setType("text/*");
shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, shareText);
startActivity(shareIntent);
}
else
{
Toast.makeText(getSherlockActivity(), "Please install the LinkedIn app to share your result", Toast.LENGTH_LONG).show();
}
then
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setClassName("com.linkedin.android",
"com.linkedin.android.infra.deeplink.DeepLinkHelperActivity");
shareIntent.setType("text/*");
shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, shareText);
startActivity(shareIntent);
and some more,but not working.
Thanks in advance.
Use this to share your text to linkedin
Intent linkedinIntent = new Intent(Intent.ACTION_SEND);
linkedinIntent.setType("text/plain");
linkedinIntent.putExtra(Intent.EXTRA_TEXT, text1);
boolean linkedinAppFound = false;
List<ResolveInfo> matches2 = getPackageManager()
.queryIntentActivities(linkedinIntent, 0);
for (ResolveInfo info : matches2) {
if (info.activityInfo.packageName.toLowerCase().startsWith(
"com.linkedin")) {
linkedinIntent.setPackage(info.activityInfo.packageName);
linkedinAppFound = true;
break;
}
}
if (linkedinAppFound) {
startActivity(linkedinIntent);
}
else
{
Toast.makeText(MainActivity.this,"LinkedIn app not Insatlled in your mobile", 4).show();
}

How to customize the built-in chooser(dialogue box) of share intent?

Is there any way to customize the createChooser of share intent in startActivity(Intent.createChooser(i,"Share via"));?
Showing the apps not in a dialogue box maybe in scroll view as buttons
String urlToShare = "www.google.com"
code to share link twitter
try {
Intent shareIntent = ShareCompat.IntentBuilder.from(getParent())
.setType("text/plain")
.setText("Sharing text with image link \n "+urlToShare).setStream(null)
.getIntent()
.setPackage("com.twitter.android");
startActivity(shareIntent);
} catch (Exception e) {
// If we failed (not native FB app installed), try share through SEND
Intent intent = new Intent(Intent.ACTION_SEND);
String sharerUrl = "https://twitter.com/intent/tweet?text=" + urlToShare;
intent = new Intent(Intent.ACTION_VIEW, Uri.parse(sharerUrl));
startActivity(intent);
}
code to share link google plus
try {
Intent shareIntent = ShareCompat.IntentBuilder.from(getParent())
.setType("text/plain")
.setText("Sharing text with image link \n "+urlToShare).setStream(null)
.getIntent()
.setPackage("com.google.android.apps.plus");
startActivity(shareIntent);
} catch (Exception e) {
// If we failed (not native FB app installed), try share through SEND
Intent intent = new Intent(Intent.ACTION_SEND);
String sharerUrl = "https://plus.google.com/share?url=" + urlToShare;
intent = new Intent(Intent.ACTION_VIEW, Uri.parse(sharerUrl));
startActivity(intent);
}
code to share link whatsapp
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT, urlToShare);
intent.setType("text/plain");
intent.setPackage("com.whatsapp");
startActivity(intent);
Yes you can do it by getting the share options as activities and pass them to your adapter, i am posting a sample code
Intent sendIntent = new Intent(android.content.Intent.ACTION_SEND);
sendIntent.setType("text/plain");
List activities = this.getPackageManager().queryIntentActivities(sendIntent, 0);
By this you will get share Intents in activities object and then you can convert it to Object Array some thing like this
Objects[] item = activities.toArray();
for( int i=0; i<item.length; i++ ) {
ResolveInfo infoName = (ResolveInfo) items[i];
String name = info.activityInfo.name;
Drawable logo = info.loadIcon(context.getPackageManager());
// Set them to your Views
}
and when your view is clicked and you want to perform the share functionality you will do some thing like this
ResolveInfo info = (ResolveInfo) item(position);
Intent intent = new Intent(android.content.Intent.ACTION_SEND);
intent.setClassName(info.activityInfo.packageName, info.activityInfo.name);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_SUBJECT, "Your Subject");
intent.putExtra(Intent.EXTRA_TEXT, "Your Text");
startActivity(intent);
this is what i have done to share link and image to another apps something like this just try
/*
* Method to share either text or URL.
*/
private void shareTextUrl() {
Intent share = new Intent(android.content.Intent.ACTION_SEND);
share.setType("text/plain");
share.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
// Add data to the intent, the receiving app will decide
// what to do with it.
share.putExtra(Intent.EXTRA_SUBJECT, "Title Of The Post");
share.putExtra(Intent.EXTRA_TEXT, "http://www.google.com");
startActivity(Intent.createChooser(share, "Share link!"));
}
/*
* Method to share any image.
*/
private void shareImage() {
Intent share = new Intent(Intent.ACTION_SEND);
// If you want to share a png image only, you can do:
// setType("image/png"); OR for jpeg: setType("image/jpeg");
share.setType("image/*");
// Make sure you put example png image named myImage.png in your
// directory
String imagePath = Environment.getExternalStorageDirectory()
+ "/myImage.png";
File imageFileToShare = new File(imagePath);
Uri uri = Uri.fromFile(imageFileToShare);
share.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(share, "Share Image!"));
}

Android Intent directly to Facebook sharing?

Following code works perfectly,
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, "text");
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Title");
startActivity(Intent.createChooser(sharingIntent, "Share using"));
but it open a list and from this list I have to select Facebook and then everything is smooth.
But is there any config changes that can open Facebook sharing directly instead of going through the menu.
Try the following code, now the intent will open Facebook directly.
List<Intent> targetedShareIntents = new ArrayList<Intent>();
Intent facebookIntent = getShareIntent("facebook", "subject", "text_or_url");
// subject may not work, but if you have a url place it in text_or_url
if(facebookIntent != null)
targetedShareIntents.add(facebookIntent);
Intent chooser = Intent.createChooser(targetedShareIntents.remove(0), "Delen");
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[]{}));
startActivity(chooser);
// To precisely get the facebook intent use the following code
private Intent getShareIntent(String type, String subject, String text)
{
boolean found = false;
Intent share = new Intent(android.content.Intent.ACTION_SEND);
share.setType("text/plain");
// gets the list of intents that can be loaded.
List<ResolveInfo> resInfo = getActivity().getPackageManager().queryIntentActivities(share, 0);
System.out.println("resinfo: " + resInfo);
if (!resInfo.isEmpty()){
for (ResolveInfo info : resInfo) {
if (info.activityInfo.packageName.toLowerCase().contains(type) ||
info.activityInfo.name.toLowerCase().contains(type) ) {
share.putExtra(Intent.EXTRA_SUBJECT, subject);
share.putExtra(Intent.EXTRA_TEXT, text);
share.setPackage(info.activityInfo.packageName);
found = true;
break;
}
}
if (!found)
return null;
return share;
}
return null;
}
Above code is extracted from this stackoverflow-post
this should be possible, if you get first all activities, that supports your intent and then get the correct and do a explicit call. To get all activities use context.getPackageManager.queryIntentActivities(Intent, int). The coding shouldn't be a big problem.
Check this link: PackageManager docu

How to filter specific apps for ACTION_SEND intent (and set a different text for each app)

How can you filter out specific apps when using the ACTION_SEND intent? This question has been asked in various ways, but I haven't been able to gather a solution based on the answers given. Hopefully someone can help. I would like to provide the ability to share within an app. Following Android Dev Alexander Lucas' advice, I'd prefer to do it using intents and not using the Facebook/Twitter APIs.
Sharing using the ACTION_SEND intent is great, but the problem is (1) I don't want every sharing option there, I'd rather limit it to FB, Twitter, and Email, and (2) I don't want to share the same thing to each sharing app. For example, in my twitter share I'm going to include some mentions and hashtags limited it to 140 chars or less, while the facebook share is going to include a link and a feature image.
Is it possible to limit the options for ACTION_SEND (share) intent? I've seen something about using PackageManager and queryIntentActivities, but haven't been able to figure out the connection between the PackageManager and the ACTION_SEND intent.
OR
Rather than filter the sharing apps, my problem could also be solved if I could use the ACTION_SEND intent to go directly to facebook or twitter rather than popping up the dialog. If that were the case then I could create my own dialog and when they click "Facebook" create a Facebook-specific intent and just send them all the way to Facebook. Same with Twitter.
OR is it not possible? Are the Facebook and Twitter APIs the only way?
My spec called for the user to be able to choose email, twitter, facebook, or SMS, with custom text for each one. Here is how I accomplished that:
public void onShareClick(View v) {
Resources resources = getResources();
Intent emailIntent = new Intent();
emailIntent.setAction(Intent.ACTION_SEND);
// Native email client doesn't currently support HTML, but it doesn't hurt to try in case they fix it
emailIntent.putExtra(Intent.EXTRA_TEXT, Html.fromHtml(resources.getString(R.string.share_email_native)));
emailIntent.putExtra(Intent.EXTRA_SUBJECT, resources.getString(R.string.share_email_subject));
emailIntent.setType("message/rfc822");
PackageManager pm = getPackageManager();
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.setType("text/plain");
Intent openInChooser = Intent.createChooser(emailIntent, resources.getString(R.string.share_chooser_text));
List<ResolveInfo> resInfo = pm.queryIntentActivities(sendIntent, 0);
List<LabeledIntent> intentList = new ArrayList<LabeledIntent>();
for (int i = 0; i < resInfo.size(); i++) {
// Extract the label, append it, and repackage it in a LabeledIntent
ResolveInfo ri = resInfo.get(i);
String packageName = ri.activityInfo.packageName;
if(packageName.contains("android.email")) {
emailIntent.setPackage(packageName);
} else if(packageName.contains("twitter") || packageName.contains("facebook") || packageName.contains("mms") || packageName.contains("android.gm")) {
Intent intent = new Intent();
intent.setComponent(new ComponentName(packageName, ri.activityInfo.name));
intent.setAction(Intent.ACTION_SEND);
intent.setType("text/plain");
if(packageName.contains("twitter")) {
intent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.share_twitter));
} else if(packageName.contains("facebook")) {
// Warning: Facebook IGNORES our text. They say "These fields are intended for users to express themselves. Pre-filling these fields erodes the authenticity of the user voice."
// One workaround is to use the Facebook SDK to post, but that doesn't allow the user to choose how they want to share. We can also make a custom landing page, and the link
// will show the <meta content ="..."> text from that page with our link in Facebook.
intent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.share_facebook));
} else if(packageName.contains("mms")) {
intent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.share_sms));
} else if(packageName.contains("android.gm")) { // If Gmail shows up twice, try removing this else-if clause and the reference to "android.gm" above
intent.putExtra(Intent.EXTRA_TEXT, Html.fromHtml(resources.getString(R.string.share_email_gmail)));
intent.putExtra(Intent.EXTRA_SUBJECT, resources.getString(R.string.share_email_subject));
intent.setType("message/rfc822");
}
intentList.add(new LabeledIntent(intent, packageName, ri.loadLabel(pm), ri.icon));
}
}
// convert intentList to array
LabeledIntent[] extraIntents = intentList.toArray( new LabeledIntent[ intentList.size() ]);
openInChooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents);
startActivity(openInChooser);
}
I found bits of how to do this in various places, but I haven't seen all of it in one place anywhere else.
Note that this method also hides all the silly options that I don't want, like sharing over wifi and bluetooth.
Edit:
In a comment, I was asked to explain what this code is doing. Basically, it's creating an ACTION_SEND intent for the native email client ONLY, then tacking other intents onto the chooser. Making the original intent email-specific gets rid of all the extra junk like wifi and bluetooth, then I grab the other intents I want from a generic ACTION_SEND of type plain-text, and tack them on before showing the chooser.
When I grab the additional intents, I set custom text for each one.
Edit2: It's been awhile since I posted this, and things have changed a bit. If you are seeing gmail twice in the list of options, try removing the special handling for "android.gm" as suggested in a comment by #h_k below.
Since this one answer is the source of nearly all my stackoverflow reputation points, I have to at least try to keep it up to date.
If you want a customized option then you should not rely on the default dialog provided by android for this action.
What you need to do instead is roll out your own. You will need to query the PackageManager on which packages handle the action you require and then based on the reply, you apply filtering and customized text.
Specifically, take a look at the method queryIntentActivities of the PackageManager class. You build the intent that would launch the default dialog (the ACTION_SEND intent), pass that to this method and you will receive a list of objects that contain info on the activities that can handle that intent. Using that, you can choose the ones you want.
Once you build your list of packages you want to present, you need to build your own list dialog (preferably an activity with the dialog theme) which will display that list.
One thing to note though is that it's very hard to make that custom dialog look like the default one. The problem is that the theme used in that dialog is an internal theme and cannot be used by your application. You can either try to make it as similar to the native one as you want or go for a completely custom look (many apps do that like the gallery app etc)
Found a solution that works for me looking here (see the third comment on the first answer). This code looks for a valid twitter client and uses it to post the tweet. Note: It does not give you an Intent with the various Twitter clients and allow you to choose.
Share using twitter:
Intent shareIntent = findTwitterClient();
shareIntent.putExtra(Intent.EXTRA_TEXT, "test");
startActivity(Intent.createChooser(shareIntent, "Share"));
Calling this method:
public Intent findTwitterClient() {
final String[] twitterApps = {
// package // name - nb installs (thousands)
"com.twitter.android", // official - 10 000
"com.twidroid", // twidroid - 5 000
"com.handmark.tweetcaster", // Tweecaster - 5 000
"com.thedeck.android" }; // TweetDeck - 5 000 };
Intent tweetIntent = new Intent();
tweetIntent.setType("text/plain");
final PackageManager packageManager = getPackageManager();
List<ResolveInfo> list = packageManager.queryIntentActivities(
tweetIntent, PackageManager.MATCH_DEFAULT_ONLY);
for (int i = 0; i < twitterApps.length; i++) {
for (ResolveInfo resolveInfo : list) {
String p = resolveInfo.activityInfo.packageName;
if (p != null && p.startsWith(twitterApps[i])) {
tweetIntent.setPackage(p);
return tweetIntent;
}
}
}
return null;
}
Facebook will be similar using "com.facebook.katana", although you still can't set the message text (deprecated July 2011).
Code source: Intent to open twitter client on Android
Try this one for sharing only three apps-Facebook, Twitter, KakaoStory.
public void onShareClick(View v){
List<Intent> targetShareIntents=new ArrayList<Intent>();
Intent shareIntent=new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
List<ResolveInfo> resInfos=getPackageManager().queryIntentActivities(shareIntent, 0);
if(!resInfos.isEmpty()){
System.out.println("Have package");
for(ResolveInfo resInfo : resInfos){
String packageName=resInfo.activityInfo.packageName;
Log.i("Package Name", packageName);
if(packageName.contains("com.twitter.android") || packageName.contains("com.facebook.katana") || packageName.contains("com.kakao.story")){
Intent intent=new Intent();
intent.setComponent(new ComponentName(packageName, resInfo.activityInfo.name));
intent.setAction(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, "Text");
intent.putExtra(Intent.EXTRA_SUBJECT, "Subject");
intent.setPackage(packageName);
targetShareIntents.add(intent);
}
}
if(!targetShareIntents.isEmpty()){
System.out.println("Have Intent");
Intent chooserIntent=Intent.createChooser(targetShareIntents.remove(0), "Choose app to share");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetShareIntents.toArray(new Parcelable[]{}));
startActivity(chooserIntent);
}else{
System.out.println("Do not Have Intent");
showDialaog(this);
}
}
}
Thanks to #dacoinminster. I make some modifications to his answer including package names of the popular apps and sorting of those apps.
List<Intent> targetShareIntents = new ArrayList<Intent>();
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
PackageManager pm = getActivity().getPackageManager();
List<ResolveInfo> resInfos = pm.queryIntentActivities(shareIntent, 0);
if (!resInfos.isEmpty()) {
System.out.println("Have package");
for (ResolveInfo resInfo : resInfos) {
String packageName = resInfo.activityInfo.packageName;
Log.i("Package Name", packageName);
if (packageName.contains("com.twitter.android") || packageName.contains("com.facebook.katana")
|| packageName.contains("com.whatsapp") || packageName.contains("com.google.android.apps.plus")
|| packageName.contains("com.google.android.talk") || packageName.contains("com.slack")
|| packageName.contains("com.google.android.gm") || packageName.contains("com.facebook.orca")
|| packageName.contains("com.yahoo.mobile") || packageName.contains("com.skype.raider")
|| packageName.contains("com.android.mms")|| packageName.contains("com.linkedin.android")
|| packageName.contains("com.google.android.apps.messaging")) {
Intent intent = new Intent();
intent.setComponent(new ComponentName(packageName, resInfo.activityInfo.name));
intent.putExtra("AppName", resInfo.loadLabel(pm).toString());
intent.setAction(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, "https://website.com/");
intent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.share_text));
intent.setPackage(packageName);
targetShareIntents.add(intent);
}
}
if (!targetShareIntents.isEmpty()) {
Collections.sort(targetShareIntents, new Comparator<Intent>() {
#Override
public int compare(Intent o1, Intent o2) {
return o1.getStringExtra("AppName").compareTo(o2.getStringExtra("AppName"));
}
});
Intent chooserIntent = Intent.createChooser(targetShareIntents.remove(0), "Select app to share");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetShareIntents.toArray(new Parcelable[]{}));
startActivity(chooserIntent);
} else {
Toast.makeText(getActivity(), "No app to share.", Toast.LENGTH_LONG).show();
}
}
You can try the code below, it works perfectly.
Here we share to some specific apps, that are Facebook, Messenger, Twitter, Google Plus and Gmail.
public void shareIntentSpecificApps() {
List<Intent> intentShareList = new ArrayList<Intent>();
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
List<ResolveInfo> resolveInfoList = getPackageManager().queryIntentActivities(shareIntent, 0);
for (ResolveInfo resInfo : resolveInfoList) {
String packageName = resInfo.activityInfo.packageName;
String name = resInfo.activityInfo.name;
Log.d(TAG, "Package Name : " + packageName);
Log.d(TAG, "Name : " + name);
if (packageName.contains("com.facebook") ||
packageName.contains("com.twitter.android") ||
packageName.contains("com.google.android.apps.plus") ||
packageName.contains("com.google.android.gm")) {
if (name.contains("com.twitter.android.DMActivity")) {
continue;
}
Intent intent = new Intent();
intent.setComponent(new ComponentName(packageName, name));
intent.setAction(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_SUBJECT, "Your Subject");
intent.putExtra(Intent.EXTRA_TEXT, "Your Content");
intentShareList.add(intent);
}
}
if (intentShareList.isEmpty()) {
Toast.makeText(MainActivity.this, "No apps to share !", Toast.LENGTH_SHORT).show();
} else {
Intent chooserIntent = Intent.createChooser(intentShareList.remove(0), "Share via");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentShareList.toArray(new Parcelable[]{}));
startActivity(chooserIntent);
}
}
This solution shows a list of applications in a ListView dialog that resembles the chooser:
It is up to you to:
obtain the list of relevant application packages
given a package name, invoke the relevant intent
The adapter class:
import java.util.List;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class ChooserArrayAdapter extends ArrayAdapter<String> {
PackageManager mPm;
int mTextViewResourceId;
List<String> mPackages;
public ChooserArrayAdapter(Context context, int resource, int textViewResourceId, List<String> packages) {
super(context, resource, textViewResourceId, packages);
mPm = context.getPackageManager();
mTextViewResourceId = textViewResourceId;
mPackages = packages;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
String pkg = mPackages.get(position);
View view = super.getView(position, convertView, parent);
try {
ApplicationInfo ai = mPm.getApplicationInfo(pkg, 0);
CharSequence appName = mPm.getApplicationLabel(ai);
Drawable appIcon = mPm.getApplicationIcon(pkg);
TextView textView = (TextView) view.findViewById(mTextViewResourceId);
textView.setText(appName);
textView.setCompoundDrawablesWithIntrinsicBounds(appIcon, null, null, null);
textView.setCompoundDrawablePadding((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 12, getContext().getResources().getDisplayMetrics()));
} catch (NameNotFoundException e) {
e.printStackTrace();
}
return view;
}
}
and its usage:
void doXxxButton() {
final List<String> packages = ...;
if (packages.size() > 1) {
ArrayAdapter<String> adapter = new ChooserArrayAdapter(MyActivity.this, android.R.layout.select_dialog_item, android.R.id.text1, packages);
new AlertDialog.Builder(MyActivity.this)
.setTitle(R.string.app_list_title)
.setAdapter(adapter, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item ) {
invokeApplication(packages.get(item));
}
})
.show();
} else if (packages.size() == 1) {
invokeApplication(packages.get(0));
}
}
void invokeApplication(String packageName) {
// given a package name, create an intent and fill it with data
...
startActivityForResult(intent, rq);
}
The cleanest way is to copy the following classes: ShareActionProvider, ActivityChooserView, ActivityChooserModel. Add the ability to filter the intents in the ActivityChooserModel, and the appropriate support methods in the ShareActionProvider. I created the necessary classes, you can copy them into your project (https://gist.github.com/saulpower/10557956). This not only adds the ability to filter the apps you would like to share with (if you know the package name), but also to turn off history.
private final String[] INTENT_FILTER = new String[] {
"com.twitter.android",
"com.facebook.katana"
};
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.journal_entry_menu, menu);
// Set up ShareActionProvider's default share intent
MenuItem shareItem = menu.findItem(R.id.action_share);
if (shareItem instanceof SupportMenuItem) {
mShareActionProvider = new ShareActionProvider(this);
mShareActionProvider.setShareIntent(ShareUtils.share(mJournalEntry));
mShareActionProvider.setIntentFilter(Arrays.asList(INTENT_FILTER));
mShareActionProvider.setShowHistory(false);
((SupportMenuItem) shareItem).setSupportActionProvider(mShareActionProvider);
}
return super.onCreateOptionsMenu(menu);
}
I have improved #dacoinminster answer and this is the result with an example to share your app:
// Intents with SEND action
PackageManager packageManager = context.getPackageManager();
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.setType("text/plain");
List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(sendIntent, 0);
List<LabeledIntent> intentList = new ArrayList<LabeledIntent>();
Resources resources = context.getResources();
for (int j = 0; j < resolveInfoList.size(); j++) {
ResolveInfo resolveInfo = resolveInfoList.get(j);
String packageName = resolveInfo.activityInfo.packageName;
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.setComponent(new ComponentName(packageName,
resolveInfo.activityInfo.name));
intent.setType("text/plain");
if (packageName.contains("twitter")) {
intent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.twitter) + "https://play.google.com/store/apps/details?id=" + context.getPackageName());
} else {
// skip android mail and gmail to avoid adding to the list twice
if (packageName.contains("android.email") || packageName.contains("android.gm")) {
continue;
}
intent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.largeTextForFacebookWhatsapp) + "https://play.google.com/store/apps/details?id=" + context.getPackageName());
}
intentList.add(new LabeledIntent(intent, packageName, resolveInfo.loadLabel(packageManager), resolveInfo.icon));
}
Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:"));
emailIntent.putExtra(Intent.EXTRA_SUBJECT, resources.getString(R.string.subjectForMailApps));
emailIntent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.largeTextForMailApps) + "https://play.google.com/store/apps/details?id=" + context.getPackageName());
context.startActivity(Intent.createChooser(emailIntent, resources.getString(R.string.compartirEn)).putExtra(Intent.EXTRA_INITIAL_INTENTS, intentList.toArray(new LabeledIntent[intentList.size()])));
I had same problem and this accepted solution didn't helped me, if someone has same problem you can use my code snippet:
// example of filtering and sharing multiple images with texts
// remove facebook from sharing intents
private void shareFilter(){
String share = getShareTexts();
ArrayList<Uri> uris = getImageUris();
List<Intent> targets = new ArrayList<>();
Intent template = new Intent(Intent.ACTION_SEND_MULTIPLE);
template.setType("image/*");
List<ResolveInfo> candidates = getActivity().getPackageManager().
queryIntentActivities(template, 0);
// remove facebook which has a broken share intent
for (ResolveInfo candidate : candidates) {
String packageName = candidate.activityInfo.packageName;
if (!packageName.equals("com.facebook.katana")) {
Intent target = new Intent(Intent.ACTION_SEND_MULTIPLE);
target.setType("image/*");
target.putParcelableArrayListExtra(Intent.EXTRA_STREAM,uris);
target.putExtra(Intent.EXTRA_TEXT, share);
target.setPackage(packageName);
targets.add(target);
}
}
Intent chooser = Intent.createChooser(targets.remove(0), "Share Via");
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, targets.toArray(new Parcelable[targets.size()]));
startActivity(chooser);
}
Intent emailIntent = new Intent(Intent.ACTION_SENDTO,
Uri.fromParts("mailto", "android#gmail.com", null));
emailIntent.putExtra(Intent.EXTRA_SUBJECT, text);
startActivity(Intent.createChooser(emailIntent, "Send email..."));
So simple and concise. Thanks to the Open source developer, cketti for sharing this solution:
String mailto = "mailto:bob#example.org" +
"?cc=" + "alice#example.com" +
"&subject=" + Uri.encode(subject) +
"&body=" + Uri.encode(bodyText);
Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
emailIntent.setData(Uri.parse(mailto));
try {
startActivity(emailIntent);
} catch (ActivityNotFoundException e) {
//TODO: Handle case where no email app is available
}
And this is the link to his/her gist.

How to customize share intent in Android?

Now i can use the share intent to open the share dialog
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, link);
startActivity(Intent.createChooser(intent, "Share with"));
but i need the dialog not to appear and share directly to one social network for example (FB or twitter)
any advice how to do that ?
There is a way to directly open the intent you wants. You can get the list of intents and open only one.
See this code:
private void initShareIntent(String type) {
boolean found = false;
Intent share = new Intent(android.content.Intent.ACTION_SEND);
share.setType("image/jpeg");
// gets the list of intents that can be loaded.
List<ResolveInfo> resInfo = getPackageManager().queryIntentActivities(share, 0);
if (!resInfo.isEmpty()){
for (ResolveInfo info : resInfo) {
if (info.activityInfo.packageName.toLowerCase().contains(type) ||
info.activityInfo.name.toLowerCase().contains(type) ) {
share.putExtra(Intent.EXTRA_SUBJECT, "subject");
share.putExtra(Intent.EXTRA_TEXT, "your text");
share.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(myPath)) ); // Optional, just if you wanna share an image.
share.setPackage(info.activityInfo.packageName);
found = true;
break;
}
}
if (!found)
return;
startActivity(Intent.createChooser(share, "Select"));
}
}
If you wanna open twitter, do that:
initShareIntent("twi");
if facebook:
initShareIntent("face");
if mail:
initShareIntent("mail"); // or "gmail"
If you wanna show a list of intents that match with the type, insted of use the first mach, see this post: Android Intent for Twitter application
No you can't. Intent's are supposed to work this way. If you have to force a particular app to open, use explicit intents if the target apps support those. Without knowing the package names or the component names of the target apps, or the type or mime type of data, you can't force a particular app to work on generalized intents.
First, list all apps to share.
private java.util.List<ResolveInfo> showAllShareApp() {
java.util.List<ResolveInfo> mApps = new ArrayList<ResolveInfo>();
Intent intent = new Intent(Intent.ACTION_SEND, null);
intent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
intent.setType("text/plain");
PackageManager pManager = getPackageManager();
mApps = pManager.queryIntentActivities(intent,
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
return mApps;
}
Then, select one
private void share(ResolveInfo appInfo) {
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
if (appInfo != null) {
sendIntent
.setComponent(new ComponentName(
appInfo.activityInfo.packageName,
appInfo.activityInfo.name));
}
sendIntent.setType("text/plain");
// startActivity(Intent.createChooser(sendIntent, "Share"));
startActivity(sendIntent);
}
Here's an sample project.Hope it helps.
You can get all email client using ACTION_SENDTO like
Intent getMailClients = new Intent(Intent.ACTION_SENDTO);
getMailClients.setData(Uri.parse("mailto:"));
final PackageManager pm = this.getPackageManager();
final List<ResolveInfo> emailsClients = pm.queryIntentActivities(getMailClients, 0);
if (emailsClients.size() == 0) {
Toast.makeText(this, "There are no email clients installed", Toast.LENGTH_LONG).show();
return;
}
and then create your own chooser(dialog with list of founded apps). When user click on item you can do smth like this.
Intent sendMailIntent = new Intent(Intent.ACTION_SEND);
sendMailIntent.setType(some type like text/plain or other you need);
...
there you can set SUBJECT,EMAILTO, attach files
...
final List<ResolveInfo> matches = pm.queryIntentActivities(sendMailIntent, 0);
ResolveInfo sendingProgramm = null;
for (final ResolveInfo info : matches) {
if (info.activityInfo.packageName.equals(clickedResolveInfo.activityInfo.packageName)) {
sendingProgramm = info;
sendMailIntent
.setClassName(sendingProgramm.activityInfo.packageName, sendingProgramm.activityInfo.name);
break;
}
}
startActivity(sendMailIntent);
Maybe it will help you.

Categories

Resources