Wrapping Intent in LabeledIntent for display purpo

2019-04-29 22:38发布

问题:

The Requirements:

I have a "share" button in my app. I have a requirement to share via Facebook. I need to have the option whether or not the native Facebook app is installed. Our decision is to send the user to facebook.com to share if the app is not installed.

The Current State:

I can detect when the native app is not installed (via the package name), and add additional intents to the chooser.

The Problem:

The item the user has to select to share via "Facebook's Website" says, "Browser" and has the Android Browser icon. The LabeledIntent item does not appear and I get a "No activity found for Intent { act=android.intent.action.VIEW dat=...}

The Code (simplified...):

Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_SUBJECT, "check this out");
intent.putExtra(Intent.EXTRA_TEXT, urlToShare);
boolean facebookInstalled = false;

Intent chooser = Intent.createChooser(intent, "Share this link!");
if (!facebookInstalled)
{
    Intent urlIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.facebook.com/sharer/sharer.php?u=" + Uri.encode(urlToShare)));
    Intent niceUrlIntent = new LabeledIntent(urlIntent, context.getApplicationContext().getPackageName(), "Facebook's Website", R.drawable.icon);

    // Ideally I would only add niceUrlIntent in the end, but that doesn't add anything to the chooser as-is
    chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[urlIntent, niceUrlIntent]);
}
context.startActivity(chooser);

The Solution

The solution as @CommonsWare pointed out, is to use the LabeledIntent to wrap an intent that goes to a new Activity I create, that simply sends a ACTION_VIEW intent to the appropriate Uri.

Intent myActivity = new Intent(context, ViewUriActivity.class);
myActivity.putExtra(ViewUriActivity.EXTRA_URI, "http://...");
Intent niceUrlIntent = new LabeledIntent(myActivity, context.getApplicationContext().getPackageName(), "Facebook's Website", R.drawable.icon);
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[]{niceUrlIntent});

The ViewUriActivity looks like this:

public final class ViewUriActivity extends Activity
{
    public static final String EXTRA_URI = ViewUriActivity.class.getSimpleName() + "EXTRA_URI";

    protected void onCreate(final Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        Intent urlIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(getIntent().getExtras().getString(EXTRA_URI)));
        startActivity(urlIntent);
        finish();
    }
}

回答1:

Though undocumented, looks like LabeledIntents only work on resolved Intents. So unless the intent already has a specific activity and package defined you will not be able to use it.

This is not surprising since there may be many Activities that might get resolved for one LabeledIntent and your chooserActivity will show all icons and names as same.

So in your case you will have to resolve the acctivity first and then use LabeledIntent. But this might result in user not able to choose browser of his choice. Use below function to get LabeledIntent from you intent.

Intent urlIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.facebook.com/sharer/sharer.php?u=" + Uri.encode(urlToShare)));
Intent niceUrlIntent = getLabelintent(urlIntent, "Facebook's Website", R.drawable.icon);

And getLabelIntent

public LabeledIntent getLabelintent(Intent in, String name, int drawable) {
    PackageManager pm = getPackageManager();
    ComponentName launchname = in.resolveActivity(pm);
    if (launchname != null) {
        Intent resolved = new Intent();
        resolved.setComponent(launchname);
        resolved.setData(in.getData());
        LabeledIntent niceUrlIntent = new LabeledIntent(resolved,
                getPackageName(), name, drawable);

        return niceUrlIntent;
    }
    return null;
}