web-dev-qa-db-ja.com

AndroidとFacebookは意図を共有します

私はAndroidアプリを開発していますが、Androidの共有インテントを使用してアプリ内からアプリのユーザーのステータスを更新する方法を知りたいと思っています。

FacebookのSDKを調べたところ、これは簡単に実行できるように見えますが、ユーザーが通常のShare Intentポップアップウィンドウを使用して実行できるようにしたいのですが。ここに見られる:

pop up

私は通常の共有インテントコードを試しましたが、これはもはやFacebookでは機能しないようです。

public void invokeShare(Activity activity, String quote, String credit) {
    Intent shareIntent = new Intent(Android.content.Intent.ACTION_SEND);
    shareIntent.setType("text/plain");
    shareIntent.putExtra(Android.content.Intent.EXTRA_SUBJECT, activity.getString(R.string.share_subject));
    shareIntent.putExtra(Android.content.Intent.EXTRA_TEXT, "Example text");    

    activity.startActivity(Intent.createChooser(shareIntent, activity.getString(R.string.share_title)));
}

更新:さらに掘り下げたところ、まだ解決されていないFacebookのアプリのバグのように見えます! ( facebookのバグ )当面は、「共有が機能しない!!!」という否定的なことを我慢しなければならないようです。レビュー。乾杯Facebook:*(

81
Joseph Woodward

Facebookアプリケーションは、EXTRA_SUBJECTまたはEXTRA_TEXTフィールドを処理しません。

バグリンクは次のとおりです。 https://developers.facebook.com/bugs/33261962681642

ありがとう@billynomates:

問題は、EXTRA_TEXTフィールドにURLを入力すると、does動作することです。意図的にテキストを削除しているようです。

92
Göksel Güren

どうやら(2014年現在)Facebookで sharer.php URL を開いているか、Androidインテントをより特殊な方法で使用している場合でも、共有画面をカスタマイズすることはできません。たとえば、これらの回答を参照してください。

とにかく、プレーンインテントを使用すると、あなたはcanはまだURLを共有できますが、デフォルトテキストは共有しませんbillynomatesのコメント 。 (また、共有するURLがない場合は、空の[投稿の書き込み](つまり、ステータスの更新)ダイアログでFacebookアプリを起動するのも同様に簡単です。以下のコードを使用しますが、EXTRA_TEXTは省略します。)

Facebook SDKを使用しないnotであることがわかった最良のソリューションを次に示します。

このコードは、公式のFacebookアプリがインストールされている場合は直接開き、それ以外の場合はブラウザーでsharer.phpを開くことにフォールバックします。 (この質問の他の解決策のほとんどは、 巨大な「…を使用してアクションを完了する」ダイアログ を表示しますが、これは最適ではありませんまったく!)

String urlToShare = "https://stackoverflow.com/questions/7545254";
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
// intent.putExtra(Intent.EXTRA_SUBJECT, "Foo bar"); // NB: has no effect!
intent.putExtra(Intent.EXTRA_TEXT, urlToShare);

// See if official Facebook app is found
boolean facebookAppFound = false;
List<ResolveInfo> matches = getPackageManager().queryIntentActivities(intent, 0);
for (ResolveInfo info : matches) {
    if (info.activityInfo.packageName.toLowerCase().startsWith("com.facebook.katana")) {
        intent.setPackage(info.activityInfo.packageName);
        facebookAppFound = true;
        break;
    }
}

// As fallback, launch sharer.php in a browser
if (!facebookAppFound) {
    String sharerUrl = "https://www.facebook.com/sharer/sharer.php?u=" + urlToShare;
    intent = new Intent(Intent.ACTION_VIEW, Uri.parse(sharerUrl));
}

startActivity(intent);

com.facebook.katana パッケージ名については、 MatheusJardimBのコメント を参照してください。)

FacebookアプリがインストールされているNexus 7(Android 4.4)では、結果は次のようになります。

enter image description here

109
Jonik

通常の方法

求めているものを作成する通常の方法は、次のことを行うことです。

    Intent intent = new Intent(Intent.ACTION_SEND);
    intent.setType("text/plain");
    intent.putExtra(Intent.EXTRA_TEXT, "The status update text");
    startActivity(Intent.createChooser(intent, "Dialog title text"));

これは問題なく機能します。

代替方法(たぶん)

これを行うことの潜在的な問題は、電子メール、SMSなどを介してメッセージを送信することも許可していることです。次のコードは、ユーザーが電子メールを送信できるようにするアプリケーションで使用しているものです-Gmailを使用したメール。 Facebookでのみ動作するように変更できると思います。

エラーや例外にどのように応答するのかわかりません(Facebookがインストールされていない場合に発生するのではないかと推測しています)ので、少しテストする必要があるかもしれません。

    try {
        Intent emailIntent = new Intent(Android.content.Intent.ACTION_SEND);
        String[] recipients = new String[]{"e-mail address"};
        emailIntent.putExtra(Android.content.Intent.EXTRA_EMAIL, recipients);
        emailIntent.putExtra(Android.content.Intent.EXTRA_SUBJECT, "E-mail subject");
        emailIntent.putExtra(Android.content.Intent.EXTRA_TEXT, "E-mail text");
        emailIntent.setType("plain/text"); // This is incorrect MIME, but Gmail is one of the only apps that responds to it - this might need to be replaced with text/plain for Facebook
        final PackageManager pm = getPackageManager();
        final List<ResolveInfo> matches = pm.queryIntentActivities(emailIntent, 0);
        ResolveInfo best = null;
        for (final ResolveInfo info : matches)
            if (info.activityInfo.packageName.endsWith(".gm") ||
                    info.activityInfo.name.toLowerCase().contains("gmail")) best = info;
                if (best != null)
                    emailIntent.setClassName(best.activityInfo.packageName, best.activityInfo.name);
                startActivity(emailIntent);
    } catch (Exception e) {
        Toast.makeText(this, "Application not found", Toast.LENGTH_SHORT).show();
    }
15
Michell Bak

これが私がしたことです(テキスト用)。コードでは、クリップボードに必要なテキストをコピーします。個人が初めて共有インテントボタンを使用しようとすると、Facebookで共有するかどうかを説明する通知がポップアップ表示されます。「Facebook」をクリックしてから長押しして貼り付ける必要がありますAndroidインテントシステムが破損しています)。次に、関連情報がフィールドにあります。ユーザーが苦情を申し立てることができるように、この投稿へのリンクを含めることもできます...

private void setClipboardText(String text) { // TODO
    int sdk = Android.os.Build.VERSION.SDK_INT;
    if(sdk < Android.os.Build.VERSION_CODES.HONEYCOMB) {
        Android.text.ClipboardManager clipboard = (Android.text.ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
        clipboard.setText(text);
    } else {
        Android.content.ClipboardManager clipboard = (Android.content.ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); 
        Android.content.ClipData clip = Android.content.ClipData.newPlainText("text label",text);
        clipboard.setPrimaryClip(clip);
    }
}

以下は、w/priorバージョンを扱う方法です

public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case R.id.menu_item_share:
        Intent shareIntent = new Intent(Intent.ACTION_SEND);
        shareIntent.setType("text/plain");
        shareIntent.putExtra(Intent.EXTRA_TEXT, "text here");

        ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); //TODO
         ClipData clip = ClipData.newPlainText("label", "text here");
         clipboard.setPrimaryClip(clip);

        setShareIntent(shareIntent); 

        break;
    }
        return super.onOptionsItemSelected(item);
}
4
easycheese

Lollipop(21)では、Intent.EXTRA_REPLACEMENT_EXTRASを使用して、Facebookの意図を具体的にオーバーライドできます(およびリンクのみを指定します)

https://developer.Android.com/reference/Android/content/Intent.html#EXTRA_REPLACEMENT_EXTRAS

private void doShareLink(String text, String link) {
  Intent shareIntent = new Intent(Intent.ACTION_SEND);
  shareIntent.setType("text/plain");
  Intent chooserIntent = Intent.createChooser(shareIntent, getString(R.string.share_via));

  // for 21+, we can use EXTRA_REPLACEMENT_EXTRAS to support the specific case of Facebook
  // (only supports a link)
  // >=21: facebook=link, other=text+link
  // <=20: all=link
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
    shareIntent.putExtra(Intent.EXTRA_TEXT, text + " " + link);
    Bundle facebookBundle = new Bundle();
    facebookBundle.putString(Intent.EXTRA_TEXT, link);
    Bundle replacement = new Bundle();
    replacement.putBundle("com.facebook.katana", facebookBundle);
    chooserIntent.putExtra(Intent.EXTRA_REPLACEMENT_EXTRAS, replacement);
  } else {
    shareIntent.putExtra(Intent.EXTRA_TEXT, link);
  }

  chooserIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  startActivity(chooserIntent);
}
4
Simon Reggiani

共有できるのはTextorImage、両方ともIntentsを使用しません。以下のコードは、存在する場合はImageのみを共有し、Imageが存在する場合はTextのみを共有します終了しません。両方を共有したい場合は、ここから Facebook SDKを使用する必要があります。

以下のコードの代わりに他のソリューションを使用する場合、パッケージ名com.facebook.liteも指定することを忘れないでください。これはFacebook Lite。テストしていませんが、com.facebook.orcaは、必要に応じてFacebook Messengerのパッケージ名ですそれもターゲットにします。

WhatsAppTwitter と共有するためのメソッドを追加できます...

public class IntentShareHelper {

    /**
     * <b>Beware,</b> this shares only image if exists, or only text if image does not exits. Can't share both
     */
    public static void shareOnFacebook(AppCompatActivity appCompatActivity, String textBody, Uri fileUri) {
        Intent intent = new Intent(Intent.ACTION_SEND);
        intent.setType("text/plain");
        intent.putExtra(Intent.EXTRA_TEXT,!TextUtils.isEmpty(textBody) ? textBody : "");

        if (fileUri != null) {
            intent.putExtra(Intent.EXTRA_STREAM, fileUri);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.setType("image/*");
        }

        boolean facebookAppFound = false;
        List<ResolveInfo> matches = appCompatActivity.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
        for (ResolveInfo info : matches) {
            if (info.activityInfo.packageName.toLowerCase().startsWith("com.facebook.katana") ||
                info.activityInfo.packageName.toLowerCase().startsWith("com.facebook.lite")) {
                intent.setPackage(info.activityInfo.packageName);
                facebookAppFound = true;
                break;
            }
        }

        if (facebookAppFound) {
            appCompatActivity.startActivity(intent);
        } else {
            showWarningDialog(appCompatActivity, appCompatActivity.getString(R.string.error_activity_not_found));
        }
    }

    public static void shareOnWhatsapp(AppCompatActivity appCompatActivity, String textBody, Uri fileUri){...}

    private static void showWarningDialog(Context context, String message) {
        new AlertDialog.Builder(context)
                .setMessage(message)
                .setNegativeButton(context.getString(R.string.close), new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                })
                .setCancelable(true)
                .create().show();
    }
}

FileからUriを取得するには、以下のクラスを使用します。

public class UtilityFile {
    public static @Nullable Uri getUriFromFile(Context context, @Nullable File file) {
        if (file == null)
            return null;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            try {
                return FileProvider.getUriForFile(context, "com.my.package.fileprovider", file);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        } else {
            return Uri.fromFile(file);
        }
    }

    // Returns the URI path to the Bitmap displayed in specified ImageView       
    public static Uri getLocalBitmapUri(Context context, ImageView imageView) {
        Drawable drawable = imageView.getDrawable();
        Bitmap bmp = null;
        if (drawable instanceof BitmapDrawable) {
            bmp = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
        } else {
            return null;
        }
        // Store image to default external storage directory
        Uri bmpUri = null;
        try {
            // Use methods on Context to access package-specific directories on external storage.
            // This way, you don't need to request external read/write permission.
            File file = new File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), "share_image_" + System.currentTimeMillis() + ".png");
            FileOutputStream out = new FileOutputStream(file);
            bmp.compress(Bitmap.CompressFormat.PNG, 90, out);
            out.close();

            bmpUri = getUriFromFile(context, file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bmpUri;
    }    
}

書き込みFileProviderには、次のリンクを使用します: https://github.com/codepath/Android_guides/wiki/Sharing-Content-with -インテント

3

このソリューションも機能します。 Facebookがインストールされていない場合、通常の共有ダイアログを実行するだけです。ログインしていない場合は、ログイン画面に移動します。ログインしている場合は、共有ダイアログが開き、Intent Extraから「共有URL」が入力されます。

Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT, "Share url");
intent.setType("text/plain");

List<ResolveInfo> matches = getMainFragmentActivity().getPackageManager().queryIntentActivities(intent, 0);
for (ResolveInfo info : matches) {
    if (info.activityInfo.packageName.toLowerCase().contains("facebook")) {
        intent.setPackage(info.activityInfo.packageName);
    }
}

startActivity(intent);
1
Tommy

Facebookのバージョン4.0.0では、多くのことが変更されたようです。これは私のコードで正常に動作しています。お役に立てば幸いです。

    /**
     * Facebook does not support sharing content without using their SDK however
     * it is possible to share URL
     *
     * @param content
     * @param url
     */
    private void shareOnFacebook(String content, String url)
    {
        try
        {
            // TODO: This part does not work properly based on my test
            Intent fbIntent = new Intent(Intent.ACTION_SEND);
            fbIntent.setType("text/plain");
            fbIntent.putExtra(Intent.EXTRA_TEXT, content);
            fbIntent.putExtra(Intent.EXTRA_STREAM, url);
            fbIntent.addCategory(Intent.CATEGORY_LAUNCHER);
            fbIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                    | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
            fbIntent.setComponent(new ComponentName("com.facebook.katana",
                    "com.facebook.composer.shareintent.ImplicitShareIntentHandler"));

            startActivity(fbIntent);
            return;
        }
        catch (Exception e)
        {
            // User doesn't have Facebook app installed. Try sharing through browser.
        }

        // If we failed (not native FB app installed), try share through SEND
        String sharerUrl = "https://www.facebook.com/sharer/sharer.php?u=" + url;
        SupportUtils.doShowUri(this.getActivity(), sharerUrl);
    }
1
Hesam

Facebookアプリをリンクで開くために行ったこと

shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setComponent(new ComponentName("com.facebook.katana",
                    "com.facebook.katana.activity.composer.ImplicitShareIntentHandler"));

shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT,  videoUrl);
0
Nayanesh Gupte

FacebookはIntent.EXTRA_TEXTとプレーンテキストデータを共有することはできませんが、これを使用してFacebookのメッセンジャーとテキスト+リンクを共有できます。

            Intent sendIntent = new Intent();
            sendIntent.setAction(Intent.ACTION_SEND);
            sendIntent.putExtra(Intent.EXTRA_TEXT, text+url link);
            sendIntent.setType("text/plain");
            sendIntent.setPackage("com.facebook.orca");
            startActivity(sendIntent);
0
kiran boghra
    public void invokeShare(Activity activity, String quote, String credit) {
    Intent shareIntent = new Intent(Android.content.Intent.ACTION_SEND);
    shareIntent.setType("text/plain");
    shareIntent.putExtra(Android.content.Intent.EXTRA_SUBJECT, activity.getString(R.string.share_subject));
    shareIntent.putExtra(Android.content.Intent.EXTRA_TEXT, "Example text");    
    shareIntent.putExtra("com.facebook.platform.extra.APPLICATION_ID", activity.getString(R.string.app_id));                        
    activity.startActivity(Intent.createChooser(shareIntent, activity.getString(R.string.share_title)));
}

アプリからFacebookにメッセージを渡す最も簡単な方法は、プログラムでクリップボードにコピーし、貼り付けるオプションがあることをユーザーに警告することです。ユーザーが手動で行う必要がなくなります。私のアプリは貼り付けられませんが、ユーザーが貼り付ける可能性があります。

...
if (app.equals("facebook")) {
    // overcome fb 'putExtra' constraint;
    // copy message to clipboard for user to paste into fb.
    ClipboardManager cb = (ClipboardManager) 
            getSystemService(Context.CLIPBOARD_SERVICE);
    ClipData clip = ClipData.newPlainText("post", msg);
    cb.setPrimaryClip(clip);

    // tell the to PASTE POST with option to stop showing this dialogue
    showDialog(this, getString(R.string.facebook_post));
}
startActivity(appIntent);
...
0
Ned