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);
Related
I'm implementing custom share feature for ACTION_SEND intent. I want to exclude my own app from sharing list. To achieve this I'm getting all suitable activities using getPackageManager().queryIntentActivityOptions(...) and then checking the package.
The problem is that getPackageManager().queryIntentActivityOptions(...) returns me a list of ResolveInfo objects where priority is always 0 and apps are ordered wrong - not like in the default share dialog. Thus apps don't have a proper order in a list and it's not convenient for user.
Here is a code which does sharing:
public void shareExcludingApp(String packageNameToExclude, Uri imagePath) {
List<Intent> targetedShareIntents = new ArrayList<>();
Intent share = new Intent(android.content.Intent.ACTION_SEND);
share.setType("image/*");
List<ResolveInfo> resInfo = mContext.getPackageManager().queryIntentActivities(createShareIntent(imagePath), 0);
if (!resInfo.isEmpty()) {
for (ResolveInfo info : resInfo) {
Intent targetedShare = createShareIntent(imagePath);
if (!info.activityInfo.packageName.equalsIgnoreCase(packageNameToExclude)) {
targetedShare.setPackage(info.activityInfo.packageName);
targetedShareIntents.add(targetedShare);
}
}
Intent chooserIntent = Intent.createChooser(targetedShareIntents.remove(0), mContext.getString(R.string.choose_an_app));
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[]{}));
mContext.startActivity(chooserIntent);
}
}
private Intent createShareIntent(Uri uri) {
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("image/*");
share.putExtra(Intent.EXTRA_STREAM, uri);
return share;
}
Am I configuring the intent wrong? Do I need to supply more data somewhere?
Thanks
Update:
Thanks to #CommonsWare I realized that I shouldn't use priority to order the list myself, instead the list should be sorted already (queryIntentActivities):
Returns a List of ResolveInfo objects containing one entry for each matching activity, ordered from best to worst.
But it's not sorted properly in my case and I'm getting activities mixed up. Can you please help me?
I want to use the directshare feature, but i need to exclude apps.
The excluding part works pretty well, i am just giving an array of intents to the chooser, while the intents are only including one specific application.
But doing this directshare does not work.
Directshare only seems to be working when giving exactly one intent to the chooser.
Is it possible to exclude apps and use directshare?
Code Snippets:
Sharing with a list of intents (How to filter specific apps for ACTION_SEND intent (and set a different text for each app)) :
final Intent chooserIntent = Intent.createChooser(targetShareIntents.remove(0), "Share with: ");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetShareIntents.toArray(new Parcelable[]{}));
activity.startActivity(chooserIntent);
Sharing with directshare, but no excluding:
final Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
sendIntent.setType("text/plain");
activity.startActivity(Intent.createChooser(sendIntent, "Share with:"));
I ran into the same problem with Direct Share, and found that it only seems to work for the target intent passed to createChooser().
My kludgy work-around was to lookup "com.android.mms" and pass that intent to createChooser() and the others in the targetedShareIntents array, which means that at least Direct Share works for text messages.
Note for some apps, not setting the class name in targetedShareIntents means you end up with Android System appearing in chooser instead.
For me this solution isn't good enough, and I'm leaning towards not excluding my own app from the list. Hopefully my efforts will lead someone to something better.
Code below is a variation on examples found here:
Custom filtering of intent chooser based on installed Android package name
I see here: http://stackoverflow.com/a/23036439 that saulpower may have a better solution, but I can't get it to work with my UI.
private void shareExludingApp(Intent intent, String packageNameToExclude, String title) {
List<Intent> targetedShareIntents = new ArrayList<Intent>();
List<ResolveInfo> resInfo = getPackageManager().queryIntentActivities(intent, 0);
Intent directShare = null;
if (!resInfo.isEmpty()) {
for (ResolveInfo info : resInfo) {
Intent targetedShare = new Intent(intent);
if (!info.activityInfo.packageName.startsWith(packageNameToExclude)) {
targetedShare.setPackage(info.activityInfo.packageName);
targetedShare.setClassName(info.activityInfo.packageName,
info.activityInfo.name);
if (directShare == null && info.activityInfo.packageName.equals("com.android.mms")) {
directShare = targetedShare;
} else {
targetedShareIntents.add(targetedShare);
}
}
}
}
if (targetedShareIntents.size() > 0) {
if (directShare == null) {
directShare = targetedShareIntents.remove(0);
}
Intent chooserIntent = Intent.createChooser(directShare, title);
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS,
targetedShareIntents.toArray(new Parcelable[] {}));
startActivity(chooserIntent);
}
else {
startActivity(Intent.createChooser(intent, title));
}
}
Usage:
shareExludingApp(intent, getPackageName(), "Share via");
If the user chooses Twitter, I want to send an abbreviated text field (due to character limit). From this SO post -- Branching the Android Share Intent extras depending on which method they choose to share -- I learned that I can implement targeted intents. However, when I use the code below, a number of apps show as "Android System" and Twitter does not show up in the dialog. I even removed the if block trying to catch Twitter, and it still did not appear.
List<Intent> targetedShareIntents = new ArrayList<Intent>();
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
PackageManager pm = rootView.getContext().getPackageManager();
List<ResolveInfo> activityList = pm.queryIntentActivities(sharingIntent, 0);
for(final ResolveInfo app : activityList){
String packageName = app.activityInfo.packageName;
Intent targetedShareIntent = new Intent(Intent.ACTION_SEND);
targetedShareIntent.setType("text/plain");
if(TextUtils.equals(packageName, TWITTER_PACKAGE_NAME)){
targetedShareIntent.putExtra(Intent.EXTRA_TEXT, getTextToShare(data, "Twitter"));
} else {
targetedShareIntent.putExtra(Intent.EXTRA_SUBJECT, data.getTitle());
targetedShareIntent.putExtra(Intent.EXTRA_TEXT, getTextToShare(data));
}
targetedShareIntent.setPackage(packageName);
targetedShareIntents.add(targetedShareIntent);
}
Intent chooserIntent = Intent.createChooser(targetedShareIntents.remove(targetedShareIntents.size() - 1), "Share this story");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[]{}));
startActivity(chooserIntent);
I'm not really sure what's going on with the following:
Intent.createChooser(targetedShareIntents.remove(targetedShareIntents.size() - 1), "Share this story");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[]{}));
In the SO post, targetedShareIntents.remove(0) was used although targetedShareIntents.remove(targetedShareIntents.size() - 1) was proposed as a more reusable solution. Any help or explanations on this is greatly appreciated.
I think TextUtils.equals(packageName, TWITTER_PACKAGE_NAME) can't find exactly com.twitter.android package name, so you need to try below code for match Twitter package name
if(packageName.toLowerCase().startsWith("com.twitter")){
targetedShareIntent.putExtra(Intent.EXTRA_TEXT, getTextToShare(data, "Twitter"));
} else {
targetedShareIntent.putExtra(Intent.EXTRA_SUBJECT, data.getTitle());
targetedShareIntent.putExtra(Intent.EXTRA_TEXT, getTextToShare(data));
}
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)
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);
}