共享意图 - 如果共享太多项目,则默默地失败

时间:2015-12-25 15:33:19

标签: android android-intent share

我与附加功能共享媒体并遇到以下问题:如果我共享太多项目,则共享意图将无声地失败。日志中没有调试消息或类似的,没有延迟选择目标表...如果我共享太多项目,没有任何反应。大约有50个项目似乎是限制......

有谁知道为什么会这样?或者有解决方案?有没有办法找出我是否分享过多的uris?

public static void shareMediaUris(Activity activity, ArrayList<Uri> uris)
{
    Intent sharingIntent = new Intent(Intent.ACTION_SEND_MULTIPLE);
    sharingIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);// | Intent.FLAG_ACTIVITY_NEW_TASK);

    sharingIntent.setType("*/*");
    String[] mimetypes = {"image/*", "video/*"};
    sharingIntent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);

    sharingIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);

    finishShare(activity, sharingIntent);
}

public static void finishShare(Activity activity, Intent intent)
{
    List<ResolveInfo> resolveInfo = MainApp.get().getPackageManager().queryIntentActivities(intent, 0);
    if (!resolveInfo.isEmpty())
    {
        for (int i = resolveInfo.size() - 1; i >= 0; i--)
        {
            if (resolveInfo.get(i).activityInfo.packageName.equals(MainApp.get().getPackageName()))
                resolveInfo.remove(i);
        }

        if (resolveInfo.size() == 0)
            activity.startActivity(Intent.createChooser(intent, MainApp.get().getString(R.string.share_with)));
        else
        {
            List<Intent> targetedShareIntents = new ArrayList<Intent>();
            for (int i = 0; i < resolveInfo.size(); i++)
            {
                Intent targetedShareIntent = (Intent) intent.clone();
                targetedShareIntent.setPackage(resolveInfo.get(i).activityInfo.packageName);
                targetedShareIntent.setClassName(resolveInfo.get(i).activityInfo.packageName, resolveInfo.get(i).activityInfo.name);
                targetedShareIntents.add(targetedShareIntent);
            }
            Intent chooserIntent = Intent.createChooser(targetedShareIntents.remove(targetedShareIntents.size() - 1), activity.getString(R.string.share_with));
            chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[targetedShareIntents.size()]));
            activity.startActivity(chooserIntent);
        }
    }
    else
        activity.startActivity(Intent.createChooser(intent, MainApp.get().getString(R.string.share_with)));
}

1 个答案:

答案 0 :(得分:1)

以下是Google的问题跟踪器对此问题的了解:Issue 5878: Intent Extras Have Size Limitation。即它&#34; 按设计&#34;行为。

我设法重现了它。如果我共享500 URI s,那么如果我共享1000 URI s - 它默默无所事事(我相信,这是您的经历),如果我分享几个成千上万 - 它崩溃了(大小限制,见我的原始答案&#39;部分)。

我检查了Android的源代码 在Instrumentation类中,此代码段会启动选择器活动,而不会启动选择器活动或崩溃,具体取决于BundleIntent的大小。

        int result = ActivityManagerNative.getDefault()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, options);

更准确地说,transactNative()类的Binder方法:

public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
    Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
    return transactNative(code, data, reply, flags);
}

在两种非崩溃情况下,它返回0作为结果,即ActivityManager.START_SUCCESS。更重要的是,正在调用原始活动的onPause()

唯一的区别是,会立即调用原始活动的onResume() ,您可以将其用作提示,说明出现了问题。

但总的来说,因为选择之间的界限非常模糊,所以选择还没有开始#34;和应用程序崩溃:

  

E / JavaBinder:!!!失败的粘合剂交易! (包裹大小= 3100860)

我建议

  • 限制应用内可能的共享项目数量,以避免此行为

  • startActivity(chooserIntent)打包到try-catch块以避免因TransactionTooLargeException

  • 而导致崩溃
  • 如果在startActivity(chooserIntent)异常之后没有被抛出,但原始活动的onResume()被调用 - 将其视为异常(即通知用户,那里&#39) ;技术问题和用户必须选择较少的项目分享)

原始回答: 我认为,您只是坚持使用Intent&{39}的{强>大小限制 {{ 1}} - 它大约1MB

这是一篇很好的文章,在这里描述:Yet another post on Serializable vs Parcelable
你可以在这里阅读更多相关信息:Is there some limits in android' bundle?