Cannot share images to WeChat and Line using ACTION_SEND intent - android

My code is as below -
Intent prototype = new Intent(Intent.ACTION_SEND);
prototype.setData(uri); // uri is of the image file
prototype.setType(image/*);
prototype.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
prototype.putExtra(Intent.EXTRA_STREAM, uri);
List<ResolveInfo> resInfo = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
if (!resInfo.isEmpty())
{
for (ResolveInfo resolveInfo : resInfo)
{
if (resolveInfo.activityInfo == null)
{
continue;
}
// Retrieve the package name and class name to populate the chooser intent
Intent intent = (Intent) prototype.clone();
String packageName = resolveInfo.activityInfo.packageName;
intent.setPackage(packageName);
intent.setClassName(packageName, resolveInfo.activityInfo.name);
targetedIntents.add(intent);
}}
Intent chooserIntent = Intent.createChooser(topIntents.remove(targetedIntents.size() - 1), chooserTitle);
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedIntents.toArray(new Parcelable[] {}));
When I select WeChat and Line app from the chooser, nothing happens. Line app just displays an error that it is unable to share. WeChat doesn't give any message. Sharing works fine on Whatsapp and Hangouts using my code.
We can share images on WeChat and Line from Gallery. How does that work? Is it not a Send action intent?

I was having the same problem so I implemented the following :
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_SUBJECT,sharesubject);
shareIntent.putExtra(Intent.EXTRA_TEXT, sharetext);
shareIntent.setType("image/jpeg");
shareIntent.putExtra(Intent.EXTRA_STREAM,Uri.fromFile(destination));
shareIntent.setPackage(info.activityInfo.packageName);
//destination is the name of the file containing the image to be shared.
Note : This works only for api 23 and below.

Building share intent by ShareCompat works to me
val shareIntent = ShareCompat.IntentBuilder(context)
.setType(context.contentResolver.getType(uri))
.setStream(uri)
.setText(text)
.intent
.apply { addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) }
startActivity(Intent.createChooser(shareIntent, "chooserTitle")
I guess the key point is
mIntent.putExtra(EXTRA_CALLING_PACKAGE, launchingContext.getPackageName());
which is specified in ShareCompat.IntentBuilder(Context)

Related

Android share intent Twitter: How to share only by Tweet or Direct Message?

I need to share an image via only Tweet.
Here is my code
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("image/*");
if (mInsertableToGallery) {
mInsertableToGallery = false;
mInsertedImagePath = MediaStore.Images.Media.insertImage(getContentResolver(), mShareImage,
getResources().getString(R.string.app_name) + System.currentTimeMillis(), getResources().getString(R.string.app_name));
}
// share only 5 specific apps:
List<Intent> targetedShareIntents = new ArrayList<>();
List<ResolveInfo> resInfos = getPackageManager().queryIntentActivities(shareIntent, 0);
if (!resInfos.isEmpty()) {
for (ResolveInfo resolveInfo : resInfos) {
String packageName = resolveInfo.activityInfo.packageName;
Intent targetedShareIntent = new Intent(Intent.ACTION_SEND);
targetedShareIntent.setType("image/*");
targetedShareIntent.setPackage(packageName);
targetedShareIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(mInsertedImagePath));
if (TextUtils.equals(packageName, "com.facebook.katana") //fb
||TextUtils.equals(packageName, "com.instagram.android") //instagram
||TextUtils.equals(packageName, "jp.naver.line.android") //line
||TextUtils.equals(packageName, "com.google.android.apps.plus") // plus
||TextUtils.equals(packageName, "com.twitter.android")) // twitter
{
targetedShareIntents.add(targetedShareIntent);
}
}
}
Intent chooser = Intent.createChooser(targetedShareIntents.remove(0), "");
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[]{}));
startActivity(chooser);
and I get the result:
When click "Android System", Twitter share popup:
What I want:
How to share via Twitter only by Tweet or Direct Message ?
How to change title & icon of share item. Ex Twitter share item from "Android System" to "Tweet"?
I couldn't manage to get both Tweet and Direct Message to the front but the following code will get you either one there. Actually you can get both to the front but both appears with same name "Tweet" so its kind of unusable.
I have also included facebook, insta and tumblr.
To get Direct Message in place of tweet replace com.twitter.android.composer.ComposerActivity with com.twitter.android.DMActivity. To get both add another ' if ' for DMActivity.
Can't say surely but I don't think you can change the Icon of the package for your app.
List<Intent> targetedShareIntents = new ArrayList<Intent>();
Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND);
shareIntent.setType("image/jpeg");//("text/plain");
Uri uri = Uri.fromFile(outFile);
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
List<ResolveInfo> resInfo = getPackageManager().queryIntentActivities(shareIntent, 0);
for (ResolveInfo resolveInfo : resInfo) {
String packageName = resolveInfo.activityInfo.packageName;
Intent targetedShareIntent = new Intent(android.content.Intent.ACTION_SEND);
targetedShareIntent.setType("image/jpeg");
targetedShareIntent.putExtra(Intent.EXTRA_STREAM, uri);
if(TextUtils.equals(packageName,"com.facebook.katana")|TextUtils.equals(packageName,"com.instagram.android")
|TextUtils.equals(packageName,"com.tumblr")) {
targetedShareIntent.setPackage(packageName);
targetedShareIntents.add(targetedShareIntent);
}
if(TextUtils.equals(resolveInfo.activityInfo.name,"com.twitter.android.composer.ComposerActivity")) {
targetedShareIntent.setPackage(packageName);
targetedShareIntent.setClassName(
resolveInfo.activityInfo.packageName,
resolveInfo.activityInfo.name);
targetedShareIntents.add(targetedShareIntent);
}
}
Intent chooserIntent = Intent.createChooser(targetedShareIntents.remove(0), "Select app to share");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[]{}));
startActivity(chooserIntent);
For composing new Tweet:
public static Intent getTwitterShareIntent(Context context) {
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
shareIntent.setClassName("com.twitter.android",
"com.twitter.composer.ComposerShareActivity");
return shareIntent;
}

Creating custom chooser for share intent by package name

I have a Text in my android activity and I want give the user option to share it on social apps like whatsapp, line, facebook, twitter etc.
But I want to create a custom chooser so that it won't show unintended apps in the chooser.
I'm aware of this snippet
Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND);
shareIntent.setType("text/plain");
startActivity(Intent.createChooser(shareIntent, "Share via"));
How can I make it so that in the chooser it'd only show the apps which I can specify by their package names.
Thanks
Even though I think this question is duplicated, but since I can't find the duplicated question yet, let me provide an answer first.
List<Intent> targetedShareIntents = new ArrayList<Intent>();
Intent shareInent = new Intent(Intent.ACTION_SEND);
shareInent.setType("text/plain");
List<ResolveInfo> resInfo = activity.getPackageManager().queryIntentActivities(shareInent, 0);
// put the name of the packages you want in this ArrayList
ArrayList<String> wantedPackage = new ArrayList<>();
if (!resInfo.isEmpty()) {
for (ResolveInfo info : resInfo) {
Intent targetedShare = new Intent(android.content.Intent.ACTION_SEND);
targetedShare.setType("text/plain");
String infoPackageName = info.activityInfo.packageName.toLowerCase();
if (wantedPackage.contains(infoPackageName)) {
targetedShare.putExtra(Intent.EXTRA_TEXT, "put your text here");
targetedShare.setPackage(info.activityInfo.packageName.toLowerCase());
targetedShareIntents.add(targetedShare);
resPackageNames.add(infoPackageName);
}
}
Intent chooserIntent = Intent.createChooser(targetedShareIntents.remove(0), "Chooser title");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[]{}));
startActivity(chooserIntent);
}

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

both labels shows "WeChat" when share to wechat friend and timeline

i've a android app to share message to WeChat(without sdk).
When i directly use the StartChooser method, the display-name 'Send to Moment' and 'Send to Chat' display well.
But when i want to remove the apps i donot need using a intent filter as follows, there's problem that both display-name show 'WeChat' rather than 'Send to Moment' and 'Send to Chat'.But at the same time,their icon are right!
Who can tell me how to get the right display label?? Thank you!
Intent it = new Intent(Intent.ACTION_SEND);
it.setType("image/*");
List<ResolveInfo> resInfo = getPackageManager().queryIntentActivities(it, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
if (!resInfo.isEmpty()) {
List<Intent> targetedShareIntents = new ArrayList<Intent>();
for (ResolveInfo info : resInfo)
{
Intent targeted = new Intent(Intent.ACTION_SEND);
targeted.setType("image/*");
ActivityInfo activityInfo = info.activityInfo;
if (activityInfo.packageName.contains("tencent.mm") || etc..)
{
targeted.setClassName(activityInfo.packageName, activityInfo.name);
targeted.setPackage(activityInfo.packageName);
targeted.putExtra(Intent.EXTRA_TEXT, "share text");
targeted.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
targetedShareIntents.add(targeted);
}
}
Intent chooserIntent = Intent.createChooser(targetedShareIntents.remove(0), "Share");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[] {}));
startActivity(chooserIntent);
}
!!! update !!! :
if the wechat intent being placed in "Intent.createChooser", the label shown is right, but shown wrong label when placed in "EXTRA_INITIAL_INTENTS".
UPDATE2:
I find the answer at How to make an intent with multiple actions. Using LabeledIntent will solve the problem.Over.
Here is how I get it to work.
CharSequence label = info.loadLabel(getPackageManager());
Intent extraIntents = new LabeledIntent(targeted, activityInfo.packageName, label, info.icon);
targetedShareIntents.add(extraIntents);

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