Que eu saiba, o StackOverflow tem muitas pessoas fazendo essa pergunta de várias maneiras, mas ninguém a respondeu completamente ainda.
Minhas especificações pediam que o usuário pudesse escolher email, twitter, facebook ou SMS, com texto personalizado para cada um. Aqui está como eu consegui isso:
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);
}
Encontrei algumas dicas de como fazer isso em vários lugares, mas não vi tudo em um lugar em nenhum outro lugar.
Observe que esse método também oculta todas as opções tolas que eu não quero, como compartilhar por wifi e bluetooth.
Espero que isso ajude alguém.
Edit:
Em um comentário, fui convidado a explicar o que esse código está fazendo. Basicamente, ele cria uma ACTION_SEND
intenção SOMENTE para o cliente de email nativo e, em seguida, coloca outras intenções no seletor. Tornar a intenção original específica de e-mail se livra de todo o lixo extra, como wi-fi e bluetooth, então pego as outras intenções que eu quero de um ACTION_SEND
tipo genérico de texto sem formatação e as ajudo antes de mostrar o seletor.
Quando pego as intenções adicionais, defino o texto personalizado para cada uma.
Edit2: Já faz um tempo desde que eu postei isso, e as coisas mudaram um pouco. Se você vir o gmail duas vezes na lista de opções, tente remover o tratamento especial para "android.gm", conforme sugerido em um comentário de @h_k abaixo.
Como essa resposta é a fonte de quase todos os meus pontos de reputação no stackoverflow, tenho que pelo menos tentar mantê-la atualizada.