I had problems attaching a video file (it's always smaller than 100KB) via mms intent. Though this works perfectly well on karbonn A21 (ICS 4.0.4), the attachment fails on HTC one V (ICS 4.0.3) and lg-p920 (2.2.2). I get a toast like "unable to attach video to message"
This is the code I have
Uri uri = Uri.fromFile(videoFile);
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.setType("video/3gp");
sendIntent.setClassName("com.android.mms", "com.android.mms.ui.ComposeMessageActivity");
sendIntent.putExtra("sms_body", "some text here");
sendIntent.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(sendIntent);
Any hints/clues/pointers on what I could do would be helpful.
this problem cause because in the video/image need to add to galley:
Read code in
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android-apps/2.3.3_r1/com/android/mms/ui/ComposeMessageActivity.java
focus in addAttachment part, I saw
String path = c.getString(c.getColumnIndexOrThrow(Images.Media.DATA));
mSrc = path.substring(path.lastIndexOf('/') + 1);
mContentType = c.getString(c.getColumnIndexOrThrow(
mages.Media.MIME_TYPE));
if (TextUtils.isEmpty(mContentType)) {
throw new MmsException("Type of media is unknown.");
})
We saw the message throwed not clear and cause misunderstand.
To solve this, you need to add the file to gallery, pass the URI get from contentResolver.insert to Intent with key Intent.EXTRA_STREAM
One more experience of my when using MMS, the default Activity class use to send MMS change among devices and manufatories, so the setClass com.android.mms.ui.ComposeMessageActivity not always right, it can cause ActivityNotFoundException. When it happends, you must call setPackge("com.android.mms") and remove setClass call.
Hope it help
My approach so far has been to let the user share the video via gmail, youtube and such along with an option to share via mms
ContentValues content = new ContentValues(4);
content.put(Video.VideoColumns.TITLE, "Cool Video");
content.put(Video.VideoColumns.DATE_ADDED,
System.currentTimeMillis() / 1000);
content.put(Video.Media.MIME_TYPE, "video/3gp");
content.put(MediaStore.Video.Media.DATA, videoFile.getAbsolutePath());
ContentResolver resolver = parentActivity.get().getContentResolver();
//I use two URI's. One for the intent with mms(MMSUri) and the
//other(ShareURi) is for sharing video with other social apps like
//gmail, youtube, facebook etc.
Uri ShareUri = resolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,content);
Uri MMSUri = Uri.fromFile(videoFile);
List<ResolveInfo> resInfo = getPackageManager().queryIntentActivities(sendIntent, 0);
if(!resInfo.isEmpty())
{
for (ResolveInfo resolveInfo : resInfo)
{
String packageName = resolveInfo.activityInfo.packageName;
Intent targetIntent = new Intent(Intent.ACTION_SEND);
targetIntent.setType("video/3gp");
targetIntent.setPackage(packageName);
if(packageName.contains("mms"))
{
targetIntent.putExtra("sms_body", "Some text here");
targetIntent.putExtra(Intent.EXTRA_STREAM, MMSUri);
}
else
{
targetIntent.putExtra(Intent.EXTRA_SUBJECT, "I can has videos?");
targetIntent.putExtra(Intent.EXTRA_TITLE, "Some title here");
targetIntent.putExtra(Intent.EXTRA_TEXT,"You have gots to watch this");
targetIntent.putExtra(Intent.EXTRA_STREAM, ShareUri);
}
targetedIntents.add(targetIntent);
}
Intent chooserIntent = Intent.createChooser(targetedIntents.remove(0), "Select app to share");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedIntents.toArray(new Parcelable[]{}));
startActivity(chooserIntent);
return;
}
Toast.makeToast(this, "No intents found for this action", Toast.LENGTH_SHORT, Gravity.CENTER).show();
I try to populate my own target intents for the Intent.createChooser knowing only these would work in attaching/uploading my video
EDIT: I wont be accepting my own answer as the right one. I'm most optimistic there's a better one out there
Related
I created my own file extension (.oli). If the user clicks on a file with this extension my app starts and loads the included data. This works like expected. The problem is I would like to give the user of my app the opportunity to share a file (Example: filename.oli).
I implemented this so far:
public void shareFile(){
File file = getShareableFile(); //Creates a .oli-file
Intent shareIntent = new Intent(Intent.ACTION_SEND);
Uri uri = Uri.fromFile(file);
shareIntent.setType("*/*"); //Maybe the problem
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, name);
startActivity(Intent.createChooser(shareIntent, getString(R.string.shareDatei)));
}
The problem is, the list of apps that think they could handle sharing my file is very large because of shareIntent.setType("/"); Here are two cases that happen if you share with different apps:
If I choose an Email-app like Gmail to share my file it works how it should. The email includes the file as filename.oli . When I click on it my app gets started.
But If I choose for example the Quickmemo-app I get a message that this file can not be shared by this.
So all in all I just want to show apps in the chooserlist that can handle to share my file with the .oli extension . How do I do that? Thanks in advance!
The setType() intent method actually uses MIME types to filter apps according to the docs. So, you'll only be able to filter the apps available based on the following filters:
1.Text
sendIntent.setType("text/plain");
2. Binary
shareIntent.setType("image/jpeg");
3. Multiple content items
shareIntent.setType("image/*");
EDIT
Here's what I would likely do, I would know which apps I want to be able to share the file, like gmail since you know that works, and I would be selective about which apps are in the list. The following code comes from the answer in this SO link: How to filter specific apps for ACTION_SEND intent (and set a different text for each app)
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 would like to filter the list you see below. Only file-explorer should be choosable.
intent = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse(Environment.getExternalStorageDirectory() + "/Android/data/" + getContext().getPackageName() + "/Files");
intent.setDataAndType(uri, "*/*");
startActivity(Intent.createChooser(intent, getString(R.string.openFolder)));
EDIT:
This is not possible. There is no magic Intent that always only opens some magic app category.
First, anyone can write any app to respond to any desired implicit Intent.
Second, there is no universal definition of "file explorer". What you think a "file explorer" is may differ from what other developers think a "file explorer" is, which in turn may differ from what users think a "file explorer" is. A user's device may not even have a "file explorer", from anyone's definition.
Add this in your Intent, it would open a ES File Explorer
Intent intent = new Intent(android.content.Intent.ACTION_SEND);
intent.setType("*/*");
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(filePath)));
intent.setPackage("com.estrongs.android.pop");
startActivity(shareIntent);
You can call the below function
type is the package name of file-explorer
like if you want to share data to Twitter call it like initShareIntent("com.twitter.android");
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 = getActivity().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 Data here
share.setPackage(info.activityInfo.packageName);
found = true;
break;
}
}
if (!found) {
Toast.makeText(getActivity(), share_type + " not found in Device", Toast.LENGTH_SHORT).show();
return;
}
startActivity(Intent.createChooser(share, "Select"));
}
}
It will only open the particular app to share data. Try this and let me know if it helped you
Make sure that the directory exists then try this :
Intent fileManagers = new Intent();
fileManagers.setAction(Intent.ACTION_GET_CONTENT);
File dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
.getAbsolutePath());
Uri uri = Uri.fromFile(dir);
fileManagers.setDataAndType(uri, "file/*");
startActivity(Intent.createChooser(fileManagers, null));
I need share text to instagram but I can't use android
intent.putExtra(Intent.EXTRA_TEXT,"MY TEXT");
nothing happen.please help me to do this
Instagram have stopped accepting pre-populated capitions to increase the quality of content in the system. See this post.
http://developers.instagram.com/post/125972775561/removing-pre-filled-captions-from-mobile-sharing
Generic code for sharing text with any social app :
Step1 : Get the package name of app you wanna share :
To get the package name use adb logcat -s ActivityManager this command in windows and run the app like for example you want package name for instagram so run above command and open instagram app you would get the package name in logs
Note : the adb command listed above is for windows .
For ubntu you can use adb logcat | grep "ActivityManager"
STEP 2 : Once you got the package name of app below is generic code for sharing text .
try {
Intent shareOnAppIntent = new Intent();
shareOnAppIntent .setAction(Intent.ACTION_SEND);
shareOnAppIntent .putExtra(Intent.EXTRA_TEXT, getResources().getString(R.string.share_body));
shareOnAppIntent .setType("text/plain");
shareOnAppIntent .setPackage(PACKAGE_NAME_OF_APP);
startActivity(shareOnAppIntent );
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(ShareAppActivity.this, "APP is not installed", Toast.LENGTH_LONG).show();
}
Unfortunately Instagram doesn't receives text from intent. it receives only EXTRA_STREAM object. you can share only images of format jpeg, gif, png. Since they are not providing any SDK you cant share in any other way.
Check Instagram developer documentation here they were clearly mentioning that the accepting Intent Parameter as EXTRA_STREAM
This is the code for sharing photo in Instagram
String type = "image/*";
String filename = "/myPhoto.jpg";
String mediaPath = Environment.getExternalStorageDirectory() + filename;
createInstagramIntent(type, mediaPath);
private void createInstagramIntent(String type, String mediaPath){
// Create the new Intent using the 'Send' action.
Intent share = new Intent(Intent.ACTION_SEND);
// Set the MIME type
share.setType(type);
// Create the URI from the media
File media = new File(mediaPath);
Uri uri = Uri.fromFile(media);
// Add the URI to the Intent.
share.putExtra(Intent.EXTRA_STREAM, uri);
// Broadcast the Intent.
startActivity(Intent.createChooser(share, "Share to"));
}
Here is the intent code to share image and text in Instagram.
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("image/*");
shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
shareIntent.putExtra(Intent.EXTRA_STREAM,uri);
shareIntent.putExtra(Intent.EXTRA_TEXT,"YOUR TEXT TO SHARE IN INSTAGRAM");
shareIntent.setPackage("com.instagram.android");
return shareIntent;
I am trying to send a photo through MMS message, I am using the following known snippet
Intent i = new Intent(Intent.ACTION_SEND);
i.putExtra(Intent.EXTRA_TEXT, "This is an MMS message");
String sendfilepath = "file://" + sendfile.toString() + ".jpg";
i.putExtra(Intent.EXTRA_STREAM,Uri.parse(sendfilepath)) ;
i.setType("image/jpeg");
It works with my Sony device. The pop up menu shows the messaging app along with other apps.
But with HTC it does not show the Messaging app. It shows Bluetooth, Facebook, Mail, etc. How can I make it show the Messaging app in the "Complete action using" list
You can use this technique to check for HTC sense device and react appropriately to send the proper "version" of the intent.
Uri uri = Uri.fromFile(imgFile);
//HTC Sense intent
Intent sendIntent = new Intent("android.intent.action.SEND_MSG");
sendIntent.putExtra(Intent.EXTRA_STREAM, uri);
sendIntent.setType("image/"+type);
List<ResolveInfo> resolves = getPackageManager().queryIntentActivities(sendIntent,PackageManager.MATCH_DEFAULT_ONLY);
if (resolves.size() > 0) {
// This branch is followed only for HTC
startActivity(sendIntent);
} else {
// Else launch the non-HTC sense Intent
sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_STREAM, uri);
sendIntent.setType("image/"+type);
startActivity(Intent.createChooser(sendIntent,"Send"));
}
My app integrates e-mail where the user can submit a bug report, feedback, etc. from the app directly. I'm using the application/octet-stream as the SetType for the Intent. When you go to submit the e-mail you get the content chooser and it shows various items from Evernote, Facebook, E-mail, etc.
How can I get this chooser to only show E-mail so as not to confuse the user with all these other items that fit the content chooser type?
Thank you.
To solve this issue simply follow the official documentation. The most important consideration are:
The flag is ACTION_SENDTO, and not ACTION_SEND.
The setData of method of the intent,
intent.setData(Uri.parse("mailto:")); // only email apps should handle this
If you send an empty Extra, the if() at the end won't work and the app won't launch the email client.
This works for me. According to Android documentation. If you want to ensure that your intent is handled only by an email app (and not other text messaging or social apps), then use the ACTION_SENDTO action and include the "mailto:" data scheme. For example:
public void composeEmail(String[] addresses, String subject) {
Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:")); // only email apps should handle this
intent.putExtra(Intent.EXTRA_EMAIL, addresses);
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
https://developer.android.com/guide/components/intents-common.html#Email
I am presuming that you are using the ACTION_SEND Intent action, since you did not bother to actually state what you're using, but you agreed with #Aleadam's comment.
I'm using the application/octet-stream as the SetType for the Intent.
Nothing in that sentence limits things to email.
ACTION_SEND is a generic Intent action that can be supported by any application that wants to. All you do is indicate what data you are sharing and the MIME type of that data -- from there, it is up to the user to choose from available activities.
As #Jasoon indicates, you can try message/rfc822 as the MIME type. However, that is not indicating "only offer email clients" -- it indicates "offer anything that supports message/rfc822 data". That could readily include some application that are not email clients.
If you specifically want to send something by email, integrate JavaMail into your app, or write an email forwarding script on your Web server and invoke it, or something. If you use ACTION_SEND, you are implicitly stating that it is what the user wants that matters, and you want the user to be able to send such-and-so data by whatever means the user chooses.
Just struggled with this problem while implementing a Magic Link feature, a chooser intent for all installed email apps:
Chooser Intent Screenshot
private void openEmailApp() {
List<Intent> emailAppLauncherIntents = new ArrayList<>();
//Intent that only email apps can handle:
Intent emailAppIntent = new Intent(Intent.ACTION_SENDTO);
emailAppIntent.setData(Uri.parse("mailto:"));
emailAppIntent.putExtra(Intent.EXTRA_EMAIL, "");
emailAppIntent.putExtra(Intent.EXTRA_SUBJECT, "");
PackageManager packageManager = getPackageManager();
//All installed apps that can handle email intent:
List<ResolveInfo> emailApps = packageManager.queryIntentActivities(emailAppIntent, PackageManager.MATCH_ALL);
for (ResolveInfo resolveInfo : emailApps) {
String packageName = resolveInfo.activityInfo.packageName;
Intent launchIntent = packageManager.getLaunchIntentForPackage(packageName);
emailAppLauncherIntents.add(launchIntent);
}
//Create chooser
Intent chooserIntent = Intent.createChooser(new Intent(), "Select email app:");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, emailAppLauncherIntents.toArray(new Parcelable[emailAppLauncherIntents.size()]));
startActivity(chooserIntent);
}
There is a way more generic to do that, working with any MIME type.
See this post: How to customize share intent in Android?
It is possible to limit the choices of an intent chooser to just a few options. The code in the answer to this question is a good example. In essence, you would have to create a List of LabeledIntents to provide to the intent chooser, that will then include it in its list. Note that this solution works not on exclusion (certain apps are excluded while the rest remain) but instead you have to pick which apps to display. Hope it helps!
It works on all devices. It will show only Email Apps
public static void shareViaMail(Activity activity, String title, String body, String filePath) {
Uri URI = Uri.parse("file://" + filePath);
final Intent emailIntent = new Intent(Intent.ACTION_VIEW);
emailIntent.setData(Uri.parse("mailto:"));
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{"contact#brightsociety.com"});
if (URI != null) {
emailIntent.putExtra(Intent.EXTRA_STREAM, URI);
}
try {
activity.startActivity(emailIntent);
} catch (Exception e) {
((BaseActivity) activity).showToast("Gmail App is not installed");
e.printStackTrace();
}
}
Kotlin Answer
If you need to show only email apps and then you want to open only inbox (not open new email writing), you need to do A and B:
A) Add below code in your AndroidManifest.xml file for Android 11 because of package visibility update of Android 11 :
<queries>
<intent>
<action android:name="android.intent.action.SENDTO" />
<data android:scheme="mailto" />
</intent>
<intent>
<action android:name="android.intent.action.CHOOSER" />
</intent>
</queries>
B) Use below function to show email chooser:
// Show email app list.
fun showEmailAppList() {
// Email app list.
val emailAppLauncherIntents: MutableList<Intent?> = ArrayList()
// Create intent which can handle only by email apps.
val emailAppIntent = Intent(Intent.ACTION_SENDTO)
emailAppIntent.data = Uri.parse("mailto:")
// Find from all installed apps that can handle email intent and check version.
val emailApps = packageManager.queryIntentActivities(
emailAppIntent,
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) 0 else PackageManager.MATCH_ALL
)
// Collect email apps and put in intent list.
for (resolveInfo in emailApps) {
val packageName = resolveInfo.activityInfo.packageName
val launchIntent = packageManager.getLaunchIntentForPackage(packageName)
emailAppLauncherIntents.add(launchIntent)
}
// Create chooser with created intent list to show email apps of device.
val chooserIntent = Intent.createChooser(Intent(), "OPEN EMAIL APP")
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, emailAppLauncherIntents.toTypedArray())
startActivity(chooserIntent)
}
Result:
It works on all devices.It will show only Email Apps
public static void shareViaMail(Activity activity, String title, String body, String filePath) {
Uri URI = Uri.parse("file://" + filePath);
final Intent emailIntent = new Intent(Intent.ACTION_VIEW);
emailIntent.setData(Uri.parse("mailto:"));
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{"xyz#gmail.com"});
/*if you want to attach something*/
if (URI != null) {
emailIntent.putExtra(Intent.EXTRA_STREAM, URI);
}
try {
activity.startActivity(emailIntent);
} catch (Exception e) {
((BaseActivity) activity).showToast("Gmail App is not installed");
e.printStackTrace();
}
}
Solution is very simple:
Intent testIntent = new Intent(Intent.ACTION_VIEW);
Uri data = Uri.parse("mailto:?subject=" + "blah blah subject" + "&body=" + "blah blah body" + "&to=" + "sendme#me.com");
testIntent.setData(data);
startActivity(testIntent);
See: http://www.gaanza.com/blog/email-client-intent-android/
After a lot of searching and testing, I finally found a perfect solution. Thanks to the Open source developer, cketti for sharing his/her concise and neat 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.