通过Android共享意图分享到Facebook、Twitter

9

我目前在尝试分享文本到Gmail、Facebook和Twitter。我使用共享意图方法来分享。以下是我用来分享的代码:

Intent sharingIntent = new Intent(Intent.ACTION_SEND);
       sharingIntent.setType("plain/text");
       sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, "My text");
       startActivity(Intent.createChooser(sharingIntent,"Share using"));

上述代码只显示了像Gmail和Skype这样的共享选项。即使我已经在设备上安装了Facebook和Twitter应用程序,为什么列表中没有显示Facebook和Twitter选项?

3个回答

22

我不知道是否有人仍在阅读这篇文章,但如果还有人寻找答案,我找到了一个更简单的解决方案:

List<Intent> targetedShareIntents = new ArrayList<Intent>();

Intent facebookIntent = getShareIntent("facebook", "subject", "text");
if(facebookIntent != null)
    targetedShareIntents.add(facebookIntent);

Intent twitterIntent = getShareIntent("twitter", "subject", "text");
    if(twitterIntent != null)
        targetedShareIntents.add(twitterIntent);

Intent gmailIntent = getShareIntent("gmail", "subject", "text");
    if(gmailIntent != null)
        targetedShareIntents.add(gmailIntent);

Intent chooser = Intent.createChooser(targetedShareIntents.remove(0), "Delen");

chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[]{}));

startActivity(chooser);

getShareIntent方法(此方法搜索mime类型text / plain,您可以使用其他mime类型来搜索这些类型或使用/* /来搜索所有类型:

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;
}
如果您不想使用这种方法,您可以像这样创建Intents:
Intent normalIntent = new Intent(Intent.ACTION_SEND);
normalIntent.setType("text/plain");
normalIntent.setPackage("com.katana.facebook"); // I just know the package of Facebook, the rest you will have to search for or use my method.
normalIntent.putExtra(Intent.EXTRA_TEXT, "The text you want to share to Facebook");

针对Google+我做了这个:Intent googlePlusIntent = getShareIntent("plus", "subject", "text"); if(googlePlusIntent != null) targetedShareIntents.add(googlePlusIntent); - Kevin van Mierlo

11

在Facebook上分享的问题在于它只接受 EXTRA_TEXT 中的URL。原生FB应用程序将从该URL获取文本和图像来组成帖子。这不是“bug”,而是他们给官方应用程序的预期行为:-/

请注意,Twitter只接受纯文本格式,没有任何标记,并且最多可以有144个字符。

我自己制作了一个“分享”对话框来拦截所有不同的行为,并向每个目标意图提供它们所接受的内容:HTML、纯文本、FB URL和Twitter短文本。

以下是代码:

public class ShareHelper implements AdapterView.OnItemClickListener {
            private static final String TAG = ShareHelper.class.getSimpleName();

            private Activity mContext;
            private Dialog mDialog;
            private LayoutInflater mInflater;
            private GridView mGrid;


   private ShareIntentAdapter mAdapter;
        private int mMaxColumns;

        private List<ResolveInfo> plainTextActivities;
        private Set<String> htmlActivitiesPackages;

        private String subject;
        private String textbody;
        private CharSequence htmlbody;
        private String twitterBody;
        private String facebookBody;

        public ShareHelper(Activity context, String subject, String textbody, CharSequence htmlbody, String twitterBody, String facebookBody) {
            this.mContext = context;

            this.subject = subject;
            this.textbody = textbody;
            this.htmlbody = htmlbody;
            this.twitterBody = twitterBody;
            this.facebookBody = facebookBody;
        }

        @SuppressLint("NewApi")
        public void share() {

            this.mInflater = LayoutInflater.from(mContext);

            final Intent sendIntent = new Intent(android.content.Intent.ACTION_SEND);

            sendIntent.setType(HTTP.PLAIN_TEXT_TYPE);
            plainTextActivities = mContext.getPackageManager().queryIntentActivities(sendIntent, 0);

            if (plainTextActivities.size() > 0) { 
                htmlActivitiesPackages = new HashSet<String>();
                sendIntent.setType("text/html");
                final List<ResolveInfo> htmlActivities = mContext.getPackageManager().queryIntentActivities(sendIntent, 0);
                for (ResolveInfo resolveInfo : htmlActivities) {
                    htmlActivitiesPackages.add(resolveInfo.activityInfo.packageName);
                }

                mAdapter = new ShareIntentAdapter();

                final View chooserView = mInflater.inflate(R.layout.dialog_share_us_chooser, null);
                mGrid = (GridView) chooserView.findViewById(R.id.resolver_grid);
                mGrid.setAdapter(mAdapter);
                mGrid.setOnItemClickListener(this);

                mMaxColumns = mContext.getResources().getInteger(R.integer.maxResolverActivityColumns);
                mGrid.setNumColumns(Math.min(plainTextActivities.size(), mMaxColumns));

                AlertDialog.Builder builder;
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                    builder = new AlertDialog.Builder(mContext, AlertDialog.THEME_DEVICE_DEFAULT_LIGHT);
                } else {
                    builder = new AlertDialog.Builder(mContext);
                }
                builder.setTitle(R.string.text_share_us_title);
                builder.setView(chooserView);

                mDialog = builder.create();
                mDialog.show();
            } else {
                Toast.makeText(mContext, "No social apps installed to share ChurchLink!", Toast.LENGTH_LONG).show();
            }
        }

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

            ResolveInfo info = (ResolveInfo) mAdapter.getItem(position);

            Intent intent = new Intent(android.content.Intent.ACTION_SEND);
            intent.setClassName(info.activityInfo.packageName, info.activityInfo.name);
            intent.setType("text/plain");
            intent.putExtra(Intent.EXTRA_TITLE, subject);
            intent.putExtra(Intent.EXTRA_SUBJECT, subject);

            if (info.activityInfo.packageName.contains("facebook")) {
                intent.putExtra(Intent.EXTRA_TEXT, facebookBody);

            } else if (info.activityInfo.packageName.contains("twitter")) {
                intent.putExtra(Intent.EXTRA_TEXT, twitterBody);

            } else if (htmlActivitiesPackages.contains(info.activityInfo.packageName)) {
                intent.putExtra(Intent.EXTRA_TEXT, htmlbody);

            } else {
                intent.putExtra(Intent.EXTRA_TEXT, textbody);
            }
            Log.d(TAG, info.activityInfo.packageName);
            ((Activity) mContext).startActivity(intent);

            mDialog.dismiss();
        }

        public class ShareIntentAdapter extends BaseAdapter {

            public ShareIntentAdapter() {
                super();
            }

            @Override
            public int getCount() {
                return plainTextActivities != null? plainTextActivities.size() : 0;
            }

            @Override
            public ResolveInfo getItem(int position) {
                return plainTextActivities.get(position);
            }

            @Override
            public long getItemId(int position) {
                return position;
            }

            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                View view;
                if (convertView == null) {
                    view = mInflater.inflate(R.layout.griditem_share_us, parent, false);
                } else {
                    view = convertView;
                }
                bindView(view, plainTextActivities.get(position));
                return view;
            }

            private final void bindView(View view, ResolveInfo info) {
                TextView text = (TextView)view.findViewById(android.R.id.text1);
                ImageView icon = (ImageView)view.findViewById(android.R.id.icon);

                text.setText(info.activityInfo.applicationInfo.loadLabel(mContext.getPackageManager()).toString());
                icon.setImageDrawable(info.activityInfo.applicationInfo.loadIcon(mContext.getPackageManager()));
            }
        }
    }

看起来有些人也想要布局文件。以下是它们:

dialog_share_us_chooser.xml

<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/resolver_grid"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="center"
    android:clipToPadding="false"
    android:columnWidth="128dp"
    android:numColumns="4"
    android:padding="16dp"
    android:scrollbarStyle="outsideOverlay" />

griditem_share_us.xml(来自自己的AOSP项目):

<?xml version="1.0" encoding="utf-8"?>
<!--
/* //device/apps/common/res/any/layout/resolve_list_item.xml
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:gravity="center"
              android:orientation="vertical"
              android:layout_height="wrap_content"
              android:layout_width="match_parent"
              android:padding="16dp">
<!--               android:background="@android:drawable/activity_picker_bg" -->

    <!-- Activity icon when presenting dialog
         Size will be filled in by ResolverActivity -->
    <ImageView android:id="@android:id/icon"
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:scaleType="fitCenter" />

    <!-- Activity name -->
    <TextView android:id="@android:id/text1"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:gravity="center"
              android:minLines="2"
              android:maxLines="2"
              android:paddingLeft="4dip"
              android:paddingRight="4dip" />
<!--               android:textAppearance="android:attr/textAppearanceSmall" -->
</LinearLayout>

哦,如果可能的话,请分享你的解决方案! - Marc P
我不确定我是否正确理解了这个问题。您是说,如果我将要发布的文本存储在设备上的文件中,然后将该文件的URI放入EXTRA_TEXT字段中,那么Facebook的状态更新活动将从该文件中加载文本,准备发送? - Ogre
并不是这样,FB只允许你发布一个URL链接。他们会从这个链接中提取任何他们想要的内容来形成最终的帖子。你可以进行一些测试来猜测最佳格式的页面,以展示你在FB上真正想要的内容。我知道他们会从中提取一张图片和一些文本。 - rgrocha

4
如果你将上面的代码改为:sharingIntent.setType("text/plain");,这个问题就会解决吗?
我认为应该是text/plain而不是plain/text
来自Android开发者的参考文献

mimeType MIME类型(例如text/plain)


谢谢!@ss1271 我会修改并测试它。 - Sarah Phil
我怎么在oncreate()中调用这个适配器? - Dimitri
@Dimitri,抱歉,请问是哪个适配器? - dumbfingers
如何在新的活动类中调用ShareHelper。 - Dimitri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接