Android email chooser - android

I am writing an app that needs to send emails at the end of each transaction. I am doing the following:
Intent mail = new Intent(Intent.ACTION_SEND);
mail.setType("text/html");
mail.putExtra(Intent.EXTRA_EMAIL, new String[] { emailTo });
mail.putExtra(Intent.EXTRA_SUBJECT, "Send from Android");
mail.putExtra(Intent.EXTRA_TEXT, "Sent from Android");
startActivity(Intent.createChooser(mail,"Select Email Software..."));
What I would like to do is pre-select the email software and store it in a setting. That way, every time the email is being sent, it does not have to ask the user which email to use. I just can't seem to figure out how to invoke the chooser and get the selected value.
Any help would be greatly appreciated.

It's a common misconception to use text/plain or text/html. This will trigger any application that can handle plain or HTML text files without any context, including Google Drive, Dropbox, Evernote and Skype.
Instead use a ACTION_SENDTO, providing the mailto: Uri:
intent = new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:"));
You can then proceed using the chooser as suggested through the other answers.

Here is the solution:
private void setSpinnerValues() {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/html");
PackageManager pm = getPackageManager();
emailers = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_RESOLVED_FILTER);
if (emailers.size() == 0) {
spnEmailProgram.setEnabled(false);
return;
}
spnEmailProgram.setEnabled(true);
CharSequence[] sa = new CharSequence[emailers.size()];
int lastPosition = 0;
for (int i = 0; i < emailers.size(); i++) {
ResolveInfo r = emailers.get(i);
sa[i] = pm.getApplicationLabel(r.activityInfo.applicationInfo);
if (r.activityInfo.name.equalsIgnoreCase(Options.EmailClass)) {
lastPosition = i;
}
}
ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(this,
android.R.layout.simple_spinner_item, sa);
adapter.
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spnEmailProgram.setAdapter(adapter);
spnEmailProgram.setSelection(lastPosition);
}
Save the choice for later use:
if (emailers.size() == 0) {
Options.EmailProgram = "";
Options.EmailClass = "";
} else {
ResolveInfo r = emailers.get(spnEmailProgram.getSelectedItemPosition());
Options.EmailProgram = r.activityInfo.packageName;
Options.EmailClass = r.activityInfo.name;
}
Now, to consume it, just to the following:
Intent mail = new Intent(Intent.ACTION_SEND);
mail.setType("text/html");
Intent chooser = null;
if (Options.EmailProgram!=null && Options.EmailProgram.length()>0) {
mail.setClassName(Options.EmailProgram,Options.EmailClass);
chooser = mail;
}
fill in rest of data and start the activity
if (chooser == null) {
chooser = Intent.createChooser(mail,"Select Email Software...");
}
startActivity(chooser);

You would have to create your own chooser, possibly as an AlertDialog populated using the results of calling queryIntentActivities() on PackageManager.

Related

Email url scheme For Android

I create button that use "mailto" to send email via email applications,when i click on the button it shows 2 option(gmail,outlook). Is there a possible way to show only the outlook application?
Yes, there is a possible way. You need to get package manager first. And iterate over the list of available matches that is received via queryIntentActivities() method. And find the app by passing package name of that outlook app. Code is below.
Intent outlookIntent = new Intent(Intent.ACTION_SEND);
outlookIntent.setType("text/html");
final PackageManager pm = getPackageManager();
final List<ResolveInfo> matches = pm.queryIntentActivities(outlookIntent, 0);
String outlookActivityClass = null;
for (final ResolveInfo info : matches) {
if (info.activityInfo.packageName.equals("com.microsoft.office.outlook")) {
outlookActivityClass = info.activityInfo.name;
if (outlookActivityClass != null && !outlookActivityClass.isEmpty()) {
break;
}
}
}
outlookIntent.setClassName("com.microsoft.office.outlook", outlookActivityClass);
outlookIntent.putExtra(Intent.EXTRA_EMAIL, new String[] { "yourmail#gmail.com" });
outlookIntent.putExtra(Intent.EXTRA_SUBJECT, "Subject");
outlookIntent.putExtra(Intent.EXTRA_CC, "cc#gmail.com"); // if necessary
outlookIntent.putExtra(Intent.EXTRA_TEXT, "Email message");
outlookIntent.setData(Uri.parse("yourmail#gmail.com"));
startActivity(outlookIntent);
Hope this will help you out.

Sending message through WhatsApp

Since I found some older posts, that tell that whatsapp doesn't support this, I was wondering if something had changed and if there is a way to open a whatsapp 'chat' with a number that I'm sending through an intent?
UPDATE
Please refer to https://faq.whatsapp.com/en/android/26000030/?category=5245251
WhatsApp's Click to Chat feature allows you to begin a chat with
someone without having their phone number saved in your phone's
address book. As long as you know this person’s phone number, you can
create a link that will allow you to start a chat with them.
Use: https://wa.me/15551234567
Don't use: https://wa.me/+001-(555)1234567
Example: https://wa.me/15551234567?text=I'm%20interested%20in%20your%20car%20for%20sale
Original answer
Here is the solution
public void onClickWhatsApp(View view) {
PackageManager pm=getPackageManager();
try {
Intent waIntent = new Intent(Intent.ACTION_SEND);
waIntent.setType("text/plain");
String text = "YOUR TEXT HERE";
PackageInfo info=pm.getPackageInfo("com.whatsapp", PackageManager.GET_META_DATA);
//Check if package exists or not. If not then code
//in catch block will be called
waIntent.setPackage("com.whatsapp");
waIntent.putExtra(Intent.EXTRA_TEXT, text);
startActivity(Intent.createChooser(waIntent, "Share with"));
} catch (NameNotFoundException e) {
Toast.makeText(this, "WhatsApp not Installed", Toast.LENGTH_SHORT)
.show();
}
}
Also see http://www.whatsapp.com/faq/en/android/28000012
With this code you can open the whatsapp chat with the given number.
void openWhatsappContact(String number) {
Uri uri = Uri.parse("smsto:" + number);
Intent i = new Intent(Intent.ACTION_SENDTO, uri);
i.setPackage("com.whatsapp");
startActivity(Intent.createChooser(i, ""));
}
Simple solution, try this.
String phoneNumberWithCountryCode = "+62820000000";
String message = "Hallo";
startActivity(
new Intent(Intent.ACTION_VIEW,
Uri.parse(
String.format("https://api.whatsapp.com/send?phone=%s&text=%s", phoneNumberWithCountryCode, message)
)
)
);
I found the following solution, first you'll need the whatsapp id:
Matching with reports from some other threads here and in other forums the login name I found was some sort of:
international area code without the 0's or + in the beginning + phone number without the first 0 + #s.whatsapp.net
For example if you live in the Netherlands and having the phone number 0612325032 it would be 31612325023#s.whatsapp.net -> +31 for the Netherlands without the 0's or + and the phone number without the 0.
public void sendWhatsAppMessageTo(String whatsappid) {
Cursor c = getSherlockActivity().getContentResolver().query(ContactsContract.Data.CONTENT_URI,
new String[] { ContactsContract.Contacts.Data._ID }, ContactsContract.Data.DATA1 + "=?",
new String[] { whatsappid }, null);
c.moveToFirst();
Intent whatsapp = new Intent(Intent.ACTION_VIEW, Uri.parse("content://com.android.contacts/data/" + c.getString(0)));
c.close();
if (whatsapp != null) {
startActivity(whatsapp);
} else {
Toast.makeText(this, "WhatsApp not Installed", Toast.LENGTH_SHORT)
.show();
//download for example after dialog
Uri uri = Uri.parse("market://details?id=com.whatsapp");
Intent goToMarket = new Intent(Intent.ACTION_VIEW, uri);
}
}
This should work whether Whatsapp is installed or not.
boolean isWhatsappInstalled = whatsappInstalledOrNot("com.whatsapp");
if (isWhatsappInstalled) {
Uri uri = Uri.parse("smsto:" + "98*********7")
Intent sendIntent = new Intent(Intent.ACTION_SENDTO, uri);
sendIntent.putExtra(Intent.EXTRA_TEXT, "Hai Good Morning");
sendIntent.setPackage("com.whatsapp");
startActivity(sendIntent);
} else {
Toast.makeText(this, "WhatsApp not Installed", Toast.LENGTH_SHORT).show();
Uri uri = Uri.parse("market://details?id=com.whatsapp");
Intent goToMarket = new Intent(Intent.ACTION_VIEW, uri);
startActivity(goToMarket);
}
private boolean whatsappInstalledOrNot(String uri) {
PackageManager pm = getPackageManager();
boolean app_installed = false;
try {
pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES);
app_installed = true;
} catch (PackageManager.NameNotFoundException e) {
app_installed = false;
}
return app_installed;
}
Tested on Marshmallow S5 and it works!
Uri uri = Uri.parse("smsto:" + "phone number with country code");
Intent sendIntent = new Intent(Intent.ACTION_SENDTO, uri);
sendIntent.setPackage("com.whatsapp");
startActivity(sendIntent);
This will open a direct chat with a person, if whatsapp not installed this will throw exception, if phone number not known to whatsapp they will offer to send invite via sms or simple sms message
use this singleline code use to Sending message through WhatsApp
//NOTE : please use with country code first 2digits without plus signed
try {
String mobile = "911234567890";
String msg = "Its Working";
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://api.whatsapp.com/send?phone=" + mobile + "&text=" + msg)));
}catch (Exception e){
//whatsapp app not install
}
Here is the latest way to send a message via Whatsapp, even if the receiver's phone number is not in your Whatsapp chat or phone's Contacts list.
private fun openWhatsApp(number: String) {
try {
packageManager.getPackageInfo("com.whatsapp", PackageManager.GET_ACTIVITIES)
val intent = Intent(
Intent.ACTION_VIEW,
Uri.parse("https://wa.me/$number?text=I'm%20interested%20in%20your%20car%20for%20sale")
)
intent.setPackage("com.whatsapp")
startActivity(intent)
} catch (e: PackageManager.NameNotFoundException) {
Toast.makeText(
this,
"Whatsapp app not installed in your phone",
Toast.LENGTH_SHORT
).show()
e.printStackTrace()
}
}
intent.setPackage("com.whatsapp") will help you to avoid Open With chooser and open Whatsapp directly.
Importent Note: If You are ending in catch statement, even if Whatsapp is installed. Please add queries to manifest.xml as follows:
<queries>
<package android:name="com.whatsapp" />
</queries>
Please see this answer for more details.
To check if WhatsApp is installed in device and initiate "click to chat" in WhatsApp:
Kotlin:
try {
// Check if whatsapp is installed
context?.packageManager?.getPackageInfo("com.whatsapp", PackageManager.GET_META_DATA)
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://wa.me/$internationalPhoneNumber"))
startActivity(intent)
} catch (e: NameNotFoundException) {
Toast.makeText(context, "WhatsApp not Installed", Toast.LENGTH_SHORT).show()
}
Java:
try {
// Check if whatsapp is installed
getPackageManager().getPackageInfo("com.whatsapp", PackageManager.GET_META_DATA);
Intent intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://wa.me/" + internationalPhoneNumber));
startActivity(intent);
} catch (NameNotFoundException e) {
Toast.makeText(context, "WhatsApp not Installed", Toast.LENGTH_SHORT).show();
}
getPackageInfo() throws NameNotFoundException if WhatsApp is not installed.
The internationalPhoneNumber variable is used to access the phone number.
Reference:
https://faq.whatsapp.com/general/chats/how-to-use-click-to-chat?category=5245251
https://stackoverflow.com/a/2201999/9636037
https://stackoverflow.com/a/15931345/9636037
The following code is used by Google Now App and will NOT work for any other application.
I'm writing this post because it makes me angry, that WhatsApp does not allow any other developers to send messages directly except for Google.
And I want other freelance-developers to know, that this kind of cooperation is going on, while Google keeps talking about "open for anybody" and WhatsApp says they don't want to provide any access to developers.
Recently WhatsApp has added an Intent specially for Google Now, which should look like following:
Intent intent = new Intent("com.google.android.voicesearch.SEND_MESSAGE_TO_CONTACTS");
intent.setPackage("com.whatsapp");
intent.setComponent(new ComponentName("com.whatsapp", "com.whatsapp.VoiceMessagingActivity"));
intent.putExtra("com.google.android.voicesearch.extra.RECIPIENT_CONTACT_CHAT_ID", number);
intent.putExtra("android.intent.extra.TEXT", text);
intent.putExtra("search_action_token", ?????);
I could also find out that "search_action_token" is a PendingIntent
that contains an IBinder-Object, which is sent back to Google App and checked, if it was created by Google Now.
Otherwise WhatsApp will not accept the message.
Currently, the only official API that you may make a GET request to:
https://api.whatsapp.com/send?phone=919773207706&text=Hello
Anyways, there is a secret API program already being ran by WhatsApp
As the documentation says you can just use an URL like:
https://wa.me/15551234567
Where the last segment is the number in in E164 Format
Uri uri = Uri.parse("https://wa.me/15551234567");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
This is what worked for me :
Uri uri = Uri.parse("https://api.whatsapp.com/send?phone=" + "<number>" + "&text=" + "Hello WhatsApp!!");
Intent sendIntent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(sendIntent);
This works to me:
PackageManager pm = context.getPackageManager();
try {
pm.getPackageInfo("com.whatsapp", PackageManager.GET_ACTIVITIES);
Intent intent = new Intent();
intent.setComponent(new ComponentName(packageName,
ri.activityInfo.name));
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, element);
} catch (NameNotFoundException e) {
ToastHelper.MakeShortText("Whatsapp have not been installed.");
}
Use direct URL of whatsapp
String url = "https://api.whatsapp.com/send?phone="+number;
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
startActivity(i);
You'll want to use a URL in the following format...
https://api.whatsapp.com/send?text=text
Then you can have it send whatever text you'd like. You also have the option to specify a phone number...
https://api.whatsapp.com/send?text=text&phone=1234
What you CANNOT DO is use the following:
https://wa.me/send?text=text
You will get...
We couldn't find the page you were looking for
wa.me, though, will work if you supply both a phone number and text. But, for the most part, if you're trying to make a sharing link, you really don't want to indicate the phone number, because you want the user to select someone. In that event, if you don't supply the number and use wa.me as URL, all of your sharing links will fail. Please use app.whatsapp.com.
this is much lengthy but surly working.
enjoy your code:)
//method used to show IMs
private void show_custom_chooser(String value) {
List<ResolveInfo> list = null;
final Intent email = new Intent(Intent.ACTION_SEND);
email.setData(Uri.parse("sms:"));
email.putExtra(Intent.EXTRA_TEXT, "" + value);
email.setType("text/plain"); // vnd.android-dir/mms-sms
WindowManager.LayoutParams WMLP = dialogCustomChooser.getWindow()
.getAttributes();
WMLP.gravity = Gravity.CENTER;
dialogCustomChooser.getWindow().setAttributes(WMLP);
dialogCustomChooser.getWindow().setBackgroundDrawable(
new ColorDrawable(android.graphics.Color.TRANSPARENT));
dialogCustomChooser.setCanceledOnTouchOutside(true);
dialogCustomChooser.setContentView(R.layout.about_dialog);
dialogCustomChooser.setCancelable(true);
ListView lvOfIms = (ListView) dialogCustomChooser
.findViewById(R.id.listView1);
PackageManager pm = getPackageManager();
List<ResolveInfo> launchables = pm.queryIntentActivities(email, 0);
// ////////////new
list = new ArrayList<ResolveInfo>();
for (int i = 0; i < launchables.size(); i++) {
String string = launchables.get(i).toString();
Log.d("heh", string);
//check only messangers
if (string.contains("whatsapp")) {
list.add(launchables.get(i));
}
}
Collections.sort(list, new ResolveInfo.DisplayNameComparator(pm));
int size = launchables.size();
adapter = new AppAdapter(pm, list, MainActivity.this);
lvOfIms.setAdapter(adapter);
lvOfIms.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int position, long arg3) {
ResolveInfo launchable = adapter.getItem(position);
ActivityInfo activity = launchable.activityInfo;
ComponentName name = new ComponentName(
activity.applicationInfo.packageName, activity.name);
email.addCategory(Intent.CATEGORY_LAUNCHER);
email.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
email.setComponent(name);
startActivity(email);
dialogCustomChooser.dismiss();
}
});
dialogCustomChooser.show();
}
I'm really late here but I believe that nowadays we have shorter and better solutions to send messages through WhatsApp.
You can use the following to call the system picker, then choose which app you will use to share whatever you want.
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
sendIntent.setType("text/plain");
startActivity(sendIntent);
If you are really need to send through WhatsApp all you need to do is the following (You will skip the system picker)
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
sendIntent.setType("text/plain");
// Put this line here
sendIntent.setPackage("com.whatsapp");
//
startActivity(sendIntent);
If you need more information you can find it here: WhatsApp FAQ
private fun sendWhatsappMessage(phoneNumber:String, text:String) {
val url = if (Intent().setPackage("com.whatsapp").resolveActivity(packageManager) != null) {
"whatsapp://send?text=Hello&phone=$phoneNumber"
} else {
"https://api.whatsapp.com/send?phone=$phoneNumber&text=$text"
}
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
startActivity(browserIntent)
}
This is a much easier way to achieve this. This code checks if whatsapp is installed on the device. If it is installed, it bypasses the system picker and goes to the contact on whatsapp and prefields the text in the chat. If not installed it opens whatsapp link on your web browser.
Sending to WhatsApp Number that exist in your contact list.
Notice that we are using ACTION_SEND
Intent whatsappIntent = new Intent(Intent.ACTION_SEND);
whatsappIntent.setType("text/plain");
whatsappIntent.setPackage("com.whatsapp");
whatsappIntent.putExtra(Intent.EXTRA_TEXT, "SMS TEXT, TEXT THAT YOU NEED TO SEND");
try {
startActivityForResult(whatsappIntent, 100);
} catch (Exception e) {
Toast.makeText(YourActivity.this, "App is not installed", Toast.LENGTH_SHORT).show();
}
If Number doesn't exist in contact list. Use WhatsApp API.
String number = number_phone.getText().toString(); // I toke it from Dialog box
number = number.substring(1); // To remove 0 at the begging of number (Optional) but needed in my case
number = "962" + number; // Replace it with your country code
String url = "https://api.whatsapp.com/send?phone=" + number + "&text=" + Uri.parse("Text that you want to send to the current user");
Intent whatsappIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
whatsappIntent.setPackage("com.whatsapp");
whatsappIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
context.startActivity(whatsappIntent);
} catch (android.content.ActivityNotFoundException ex) {
Toast.makeText(YourActivity.this, "App is not installed", Toast.LENGTH_SHORT).show();
}
Check this code,
public void share(String subject,String text) {
final Intent intent = new Intent(Intent.ACTION_SEND);
String score=1000;
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_SUBJECT, score);
intent.putExtra(Intent.EXTRA_TEXT, text);
startActivity(Intent.createChooser(intent, getString(R.string.share)));
}
This works to me:
public static void shareWhatsApp(Activity appActivity, String texto) {
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.setType("text/plain");
sendIntent.putExtra(android.content.Intent.EXTRA_TEXT, texto);
PackageManager pm = appActivity.getApplicationContext().getPackageManager();
final List<ResolveInfo> matches = pm.queryIntentActivities(sendIntent, 0);
boolean temWhatsApp = false;
for (final ResolveInfo info : matches) {
if (info.activityInfo.packageName.startsWith("com.whatsapp")) {
final ComponentName name = new ComponentName(info.activityInfo.applicationInfo.packageName, info.activityInfo.name);
sendIntent.addCategory(Intent.CATEGORY_LAUNCHER);
sendIntent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_NEW_TASK);
sendIntent.setComponent(name);
temWhatsApp = true;
break;
}
}
if(temWhatsApp) {
//abre whatsapp
appActivity.startActivity(sendIntent);
} else {
//alerta - você deve ter o whatsapp instalado
Toast.makeText(appActivity, appActivity.getString(R.string.share_whatsapp), Toast.LENGTH_SHORT).show();
}
}
get the contact number whom you want to send the message and create uri for whatsapp, here c is a Cursor returning the selected contact.
Uri.parse("content://com.android.contacts/data/" + c.getString(0)));
i.setType("text/plain");
i.setPackage("com.whatsapp"); // so that only Whatsapp reacts and not the chooser
i.putExtra(Intent.EXTRA_SUBJECT, "Subject");
i.putExtra(Intent.EXTRA_TEXT, "I'm the body.");
startActivity(i);
From the documentation
To create your own link with a pre-filled message that will
automatically appear in the text field of a chat, use
https://wa.me/whatsappphonenumber/?text=urlencodedtext where
whatsappphonenumber is a full phone number in international format and
URL-encodedtext is the URL-encoded pre-filled message.
Example:https://wa.me/15551234567?text=I'm%20interested%20in%20your%20car%20for%20sale
Code example
val phoneNumber = "13492838472"
val text = "Hey, you know... I love StackOverflow :)"
val uri = Uri.parse("https://wa.me/$phoneNumber/?text=$text")
val sendIntent = Intent(Intent.ACTION_VIEW, uri)
startActivity(sendIntent)
This one worked finally for me in Kotlin:
private fun navigateToWhatsApp() {
try {
val url = "https://api.whatsapp.com/send?phone=+91${getString(R.string.contact)}"
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)).setPackage("com.whatsapp"))
} catch (e: Exception) {
showToast("Whatsapp app not installed in your device")
}
}
The following API can be used in c++ as shown in my article.
You need to define several constants:
//
#define    GroupAdmin                <YOUR GROUP ADMIN MOBILE PHONE>
#define GroupName                <YOUR GROUP NAME>
#define CLIENT_ID                <YOUR CLIENT ID>
#define CLIENT_SECRET            <YOUR CLIENT SECRET>
#define GROUP_API_SERVER        L"api.whatsmate.net"
#define GROUP_API_PATH          L"/v3/whatsapp/group/text/message/12"
#define IMAGE_SINGLE_API_URL    L"http://api.whatsmate.net/v3/whatsapp/group/image/message/12"
//
Then you connect to the API’s endpoint.
hOpenHandle = InternetOpen(_T("HTTP"), INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (hOpenHandle == NULL)
{
return false;
}
hConnectHandle = InternetConnect(hOpenHandle,
GROUP_API_SERVER,
INTERNET_DEFAULT_HTTP_PORT,
NULL, NULL, INTERNET_SERVICE_HTTP,
0, 1);
if (hConnectHandle == NULL)
{
InternetCloseHandle(hOpenHandle);
return false;
}
Then send both header and body and wait for the result that needs to be “OK”.
Step 1 - open an HTTP request:
const wchar_t *AcceptTypes[] = { _T("application/json"),NULL };
HINTERNET hRequest = HttpOpenRequest(hConnectHandle, _T("POST"), GROUP_API_PATH, NULL, NULL, AcceptTypes, 0, 0);
if (hRequest == NULL)
{
InternetCloseHandle(hConnectHandle);
InternetCloseHandle(hOpenHandle);
return false;
}
Step 2 - send the header:
std::wstring HeaderData;
HeaderData += _T("X-WM-CLIENT-ID: ");
HeaderData += _T(CLIENT_ID);
HeaderData += _T("\r\nX-WM-CLIENT-SECRET: ");
HeaderData += _T(CLIENT_SECRET);
HeaderData += _T("\r\n");
HttpAddRequestHeaders(hRequest, HeaderData.c_str(), HeaderData.size(), NULL);
Step 3 - send the message:
std::wstring WJsonData;
WJsonData += _T("{");
WJsonData += _T("\"group_admin\":\"");
WJsonData += groupAdmin;
WJsonData += _T("\",");
WJsonData += _T("\"group_name\":\"");
WJsonData += groupName;
WJsonData += _T("\",");
WJsonData += _T("\"message\":\"");
WJsonData += message;
WJsonData += _T("\"");
WJsonData += _T("}");
const std::string JsonData(WJsonData.begin(), WJsonData.end());
bResults = HttpSendRequest(hRequest, NULL, 0, (LPVOID)(JsonData.c_str()), JsonData.size());
Now just check the result:
TCHAR StatusText[BUFFER_LENGTH] = { 0 };
DWORD StatusTextLen = BUFFER_LENGTH;
HttpQueryInfo(hRequest, HTTP_QUERY_STATUS_TEXT, &StatusText, &StatusTextLen, NULL);
bResults = (StatusTextLen && wcscmp(StatusText, L"OK")==FALSE);

Opening email client via Intent (but not to send a message)

Is there a way to programically open email client, without a need to forcing message send? I just want the app to let user open his email client for email checking purposes :)
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("message/rfc822");
startActivity(Intent.createChooser(intent, ""));
This code works but it forces user to send a new message.
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_APP_EMAIL);
startActivity(intent);
startActivity(Intent.createChooser(intent, getString(R.string.ChoseEmailClient)));
That kinda worked. But it opend Gmail for me, even since I have other email clients
This code will show a dialog with a list of email clients. Clicking one will launch the application:
try {
List<String> emailClientNames = new ArrayList<String>();
final List<String> emailClientPackageNames = new ArrayList<String>();
// finding list of email clients that support send email
Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(
"mailto", "abc#gmail.com", null));
PackageManager pkgManager = AppController.getContext().getPackageManager();
List<ResolveInfo> packages = pkgManager.queryIntentActivities(intent, 0);
if (!packages.isEmpty()) {
for (ResolveInfo resolveInfo : packages) {
// finding the package name
String packageName = resolveInfo.activityInfo.packageName;
emailClientNames.add(resolveInfo.loadLabel(getPackageManager()).toString());
emailClientPackageNames.add(packageName);
}
// a selection dialog for the email clients
AlertDialog.Builder builder = new AlertDialog.Builder(MyActivity.this);
builder.setTitle("Select email client");
builder.setItems(emailClientNames.toArray(new String[]{}), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// on click we launch the right package
Intent intent = getPackageManager().getLaunchIntentForPackage(emailClientPackageNames.get(which));
startActivity(intent);
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
} catch (ActivityNotFoundException e) {
// Show error message
}
In Kotlin, but this version creates a chooser for user to pick which email app to use. You basically do what Oved does in his answer, except create an actual chooser using LabeledIntent.
fun emailAppIntent(): Intent? {
val emailIntent = Intent(Intent.ACTION_VIEW, Uri.parse("mailto:"))
val packageManager = appLaunchContext.packageManager
val activitiesHandlingEmails = packageManager.queryIntentActivities(emailIntent, 0)
if (activitiesHandlingEmails.isNotEmpty()) {
// use the first email package to create the chooserIntent
val firstEmailPackageName = activitiesHandlingEmails.first().activityInfo.packageName
val firstEmailInboxIntent = packageManager.getLaunchIntentForPackage(firstEmailPackageName)
val emailAppChooserIntent = Intent.createChooser(firstEmailInboxIntent, "")
// created UI for other email packages and add them to the chooser
val emailInboxIntents = mutableListOf<LabeledIntent>()
for (i in 1 until activitiesHandlingEmails.size) {
val activityHandlingEmail = activitiesHandlingEmails[i]
val packageName = activityHandlingEmail.activityInfo.packageName
val intent = packageManager.getLaunchIntentForPackage(packageName)
emailInboxIntents.add(
LabeledIntent(
intent,
packageName,
activityHandlingEmail.loadLabel(packageManager),
activityHandlingEmail.icon
)
)
}
val extraEmailInboxIntents = emailInboxIntents.toTypedArray()
return emailAppChooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraEmailInboxIntents)
} else {
return null
}
}
.. then later call it with
val emailChooserIntent = emailAppIntent()
if (emailChooserIntent != null) {
startActivity(emailAppIntent())
}
or handle null however you want.
I think you should replace Intent.ACTION_SEND to Intent.ACTION_VIEW, i am sure this will work as this will prompt with list of application which support MIME type "message/rfc822" so it will include your default email client in your device other than gmail app.
How about this code:
final Intent emailLauncher = new Intent(Intent.ACTION_VIEW);
emailLauncher.setType("message/rfc822");
try{
startActivity(emailLauncher);
}catch(ActivityNotFoundException e){
}
A bit more modern solution in Kotlin
fun tryVerifyMail() {
try {
val intents: List<Intent> = (packageManager.queryIntentActivities(Intent(
Intent.ACTION_SENDTO, Uri.fromParts(
"mailto", "lowhillgamesoy#gmail.com", null
)
), 0) + packageManager.queryIntentActivities(Intent(Intent.ACTION_VIEW).also {
it.type = "message/rfc822"
}, 0)).mapNotNull {
it.activityInfo.packageName
}.toSet().mapNotNull {
packageManager.getLaunchIntentForPackage(it)
}
if(intents.size > 0) {
startActivityForResult(Intent.createChooser(intents.first(), getString(R.string.verify_mail)).also {
if(intents.size > 1) {
it.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents.subList(1, intents.size - 1).toTypedArray())
}
}, OPEN_MAIL_REQUEST_CODE)
} else {
Toast.makeText(this, "Verify your e-mail by clicking the link in your e-mail inbox.", Toast.LENGTH_LONG).show()
}
} catch (e: ActivityNotFoundException) {
// Show error message
e.printStackTrace()
}
}
This also picks both mail clients only supporting ACTION_SEND and ACTION_VIEW and removes duplicates.

check if user is signed into twitter

In my app, the user is allowed to tweet something by pressing a button. I am using the following code:
boolean found = false;
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, "Blah blah");
final PackageManager pm = getPackageManager();
final List<?> activityList = pm.queryIntentActivities(intent, 0);
int len = activityList.size();
for (int i = 0; i < len; i++) {
final ResolveInfo app = (ResolveInfo) activityList.get(i);
if ("com.twitter.android.PostActivity".equals(app.activityInfo.name)) {
found = true;
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setClassName("com.twitter.android", "com.twitter.android.PostActivity");
startActivity(intent);
break;
}
}
if(!found)
showDialog(NO_APP);
The code works perfectly but I want to add a feature to it. When the user is not logged into twitter, I want to display a message saying that he is not logged in. The code, as of right now, just directs the user to the sign in page of twitter. How can I disable this and get the desired output? Thanks!!
For that you can check first that you have the twitterToken and twitterTokenSecret .
Try this way.may it helps :)
if(twitterToken!=null && twitterTokenSecret!=null
&& twitterToken.length()>0 && twitterTokenSecret.length()>0){
//do your work
}else{
//show alert dialog
}

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.

Categories

Resources