【问题标题】:How can I share multiple files via an Intent?如何通过 Intent 共享多个文件?
【发布时间】:2020-02-14 16:57:11
【问题描述】:

这是我的代码,但这是针对单文件解决方案的。

我可以像下面的单个文件一样共享多个文件和上传吗?

Button btn = (Button)findViewById(R.id.hello);

    btn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent(Intent.ACTION_SEND);

                String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/pic.png";
                File file = new File(path);

                MimeTypeMap type = MimeTypeMap.getSingleton();
                intent.setType(type.getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(path)));

                intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
                intent.putExtra(Intent.EXTRA_TEXT, "1111"); 
                startActivity(intent);
            }
        }); 

【问题讨论】:

    标签: java android android-intent


    【解决方案1】:

    可以,但您需要使用 Intent.ACTION_SEND_MULTIPLE 而不是 Intent.ACTION_SEND

    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_SEND_MULTIPLE);
    intent.putExtra(Intent.EXTRA_SUBJECT, "Here are some files.");
    intent.setType("image/jpeg"); /* This example is sharing jpeg images. */
    
    ArrayList<Uri> files = new ArrayList<Uri>();
    
    for(String path : filesToSend /* List of the files you want to send */) {
        File file = new File(path);
        Uri uri = Uri.fromFile(file);
        files.add(uri);
    }
    
    intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, files);
    startActivity(intent);
    

    这绝对可以简化,但我留下了一些行,以便您可以分解所需的每个步骤。

    更新:从 API 24 开始,共享文件 URI 将导致 FileUriExposedException。要解决此问题,您可以将 compileSdkVersion 切换为 23 或更低,也可以使用 content URIs with a FileProvider

    更新(更新)Google recently announced 需要新应用和应用更新才能针对最新版本的 Android 之一发布到 Play 商店。也就是说,如果您计划将应用程序发布到商店,则以 API 23 或更低版本为目标不再是一个有效的选择。你必须走 FileProvider 路线。

    【讨论】:

    • 不幸的是,在 facebook 上分享多张图片时,这似乎不起作用。我能够使用这篇文章中描述的解决方案使其工作:stackoverflow.com/questions/25846496/…
    • 发送不同的文件类型 image/* 和 video/* 怎么样?
    • 应该以同样的方式工作。您只需更改 setType() 调用即可获得正确的数据类型。
    • 设置类似这样的类型来发送不同的文件类型 intent.setType("*/*");这在您想要发送异构文件类型(例如发送到 Google Drive 或 Dropbox 等)的情况下会有所帮助
    • 小知识:Android 上的文件共享是魔鬼自己设计的。
    【解决方案2】:

    这是由 Mceley 的解决方案即兴创作的小改进版本。这可以用于发送异构文件列表(如图像、文档和视频),例如同时上传下载的文档、图像。

    public static void shareMultiple(List<File> files, Context context){
    
        ArrayList<Uri> uris = new ArrayList<>();
        for(File file: files){
            uris.add(Uri.fromFile(file));
        }
        final Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
        intent.setType("*/*");
        intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
        context.startActivity(Intent.createChooser(intent, context.getString(R.string.ids_msg_share)));
    }
    

    【讨论】:

    • 谢谢!值得注意的是,在我尝试过的大多数情况下,您可以拥有一个异构文件列表。基本上,mime 类型只是将应用程序响应限制为那些能够处理指定类型的应用程序,例如。如果您指定“文本/*”,谷歌照片将不会响应。但是 gmail 会响应,并且列表可以包含图像,这将被正确处理。
    【解决方案3】:

    如果您在运行 KitKat 及更高版本的设备上与其他应用程序共享文件,则需要提供 Uri 权限。


    这就是我在 KitKat 前后处理多个文件共享的方式:

    //All my paths will temporarily be retrieve into this ArrayList
    //PathModel is a simple getter/setter
    ArrayList<PathModel> pathList;
    //All Uri's are retrieved into this ArrayList
    ArrayList<Uri> uriArrayList = null;
    //This is important since we are sending multiple files
    Intent sharingIntent = new Intent(Intent.ACTION_SEND_MULTIPLE);
    //Used temporarily to get Uri references
    Uri shareFileUri;
    
    if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
    
        //My paths are stored in SQLite, I retrieve them first
        SQLiteHelper helper = new SQLiteHelper(this);
        pathList = helper.getAllAttachments(viewholderID);
        helper.close();
    
        //Create new instance of the ArrayList where the Uri will be stored
        uriArrayList = new ArrayList<>();
    
        //Get all paths from my PathModel
        for (PathModel data : pathList) {
            //Create a new file for each path
            File mFile = new File(data.getPath());
            //No need to add Uri permissions for pre-KitKat
            shareFileUri = Uri.fromFile(mFile);
            //Add Uri's to the Array that holds the Uri's
            uriArrayList.add(shareFileUri);
        }
    
    
    } else {
    
        //My paths are stored in SQLite, I retrieve them first
        SQLiteHelper helper = new SQLiteHelper(this);
        pathList = helper.getAllAttachments(viewholderID);
        helper.close();
    
        //Create new instance of the ArrayList where the Uri will be stored
        uriArrayList = new ArrayList<>();
    
        //Get all paths from my PathModel
        for (PathModel data : pathList) {
            //Create a new file for each path
            File mFile = new File(data.getPath());
            //Now we need to grant Uri permissions (kitKat>)
            shareFileUri = FileProvider.getUriForFile(getApplication(), getApplication().getPackageName() + ".provider", mFile);
            //Add Uri's to the Array that holds the Uri's
            uriArrayList.add(shareFileUri);
        }
    
        //Grant read Uri permissions to the intent
        sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    
    }
    
    //I know that the files which will be sent will be one of the following
    sharingIntent.setType("application/pdf/*|image|video/*");
    //pass the Array that holds the paths to the files
    sharingIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uriArrayList);
    //Start intent by creating a chooser
    startActivity(Intent.createChooser(sharingIntent, "Share using"));
    

    在我的例子中,路径存储在SQLite,但路径可以来自任何地方。

    【讨论】:

      【解决方案4】:
      /* 
       manifest file outside the applicationTag write these permissions
           <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
           <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> */
      
          File pictures = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
                                  //Get a top-level public external storage directory for placing files of a particular type. 
                                  // This is where the user will typically place and manage their own files, 
                                  // so you should be careful about what you put here to ensure you don't 
                                  // erase their files or get in the way of their own organization...
                                  // pulled from Standard directory in which to place pictures that are available to the user to the File object
      
                                  String[] listOfPictures = pictures.list();
                                  //Returns an array of strings with the file names in the directory represented by this file. The result is null if this file is not a directory.
      
                                  Uri uri=null; 
                                  ArrayList<Uri> arrayList = new ArrayList<>();
                                  if (listOfPictures!=null) {
                                      for (String name : listOfPictures) {
                                          uri = Uri.parse("file://" + pictures.toString() + "/" + name );
                                          arrayList.add(uri);
                                      }
                                      Intent intent = new Intent();
                                      intent.setAction(Intent.ACTION_SEND_MULTIPLE);
                                      intent.putExtra(Intent.EXTRA_STREAM, arrayList);
                                      //A content: URI holding a stream of data associated with the Intent, used with ACTION_SEND to supply the data being sent.
                                      intent.setType("image/*"); //any kind of images can support.
                                      chooser = Intent.createChooser(intent, "Send Multiple Images");//choosers title
                                       startActivity(chooser);
                                  }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-18
        • 1970-01-01
        • 1970-01-01
        • 2013-10-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多