Que yo sepa, StackOverflow tiene muchas personas haciendo esta pregunta de varias maneras, pero nadie la ha respondido por completo todavía.
Mi especificación requería que el usuario pudiera elegir correo electrónico, twitter, facebook o SMS, con texto personalizado para cada uno. Así es como lo logré:
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);
}
Encontré fragmentos de cómo hacer esto en varios lugares, pero no lo he visto en un solo lugar en ningún otro lugar.
Tenga en cuenta que este método también oculta todas las opciones tontas que no quiero, como compartir a través de wifi y bluetooth.
Espero que esto ayude a alguien.
Editar:
en un comentario, me pidieron que explicara qué está haciendo este código. Básicamente, está creando una ACTION_SEND
intención SOLAMENTE para el cliente de correo electrónico nativo, luego agrega otras intenciones en el selector. Al hacer la intención original específica del correo electrónico, se eliminan todos los archivos basura adicionales como wifi y bluetooth, luego tomo las otras intenciones que quiero de un ACTION_SEND
texto plano genérico y las agrego antes de mostrar el selector.
Cuando tomo las intenciones adicionales, establezco texto personalizado para cada una.
Edit2: Ha pasado un tiempo desde que publiqué esto, y las cosas han cambiado un poco. Si ve gmail dos veces en la lista de opciones, intente eliminar el manejo especial de "android.gm" como se sugiere en un comentario de @h_k a continuación.
Dado que esta respuesta es la fuente de casi todos mis puntos de reputación de stackoverflow, al menos tengo que tratar de mantenerla actualizada.