【问题标题】:Android Share Intent Chooser EMail Client Only仅限 Android 共享意图选择器电子邮件客户端
【发布时间】:2016-03-26 16:35:04
【问题描述】:

我正在尝试为用户创建一个选项,以便仅通过电子邮件从我的应用程序发送文件。该文件位于应用程序内部,可通过 FileProvider 访问。

这是 contentURI 看起来像content://packagename.files/files/somefile.ext

如您所见,我让用户将文件共享到 PicsArt、Google Drive、OneDrive 和 EMail。

我能够成功地将内容分享给前三个客户,因为他们是非常具体的应用程序。但是对于电子邮件,我需要用户从他在手机中安装的应用程序中选择客户端。

这是我创建的 2 组代码:

代码选项 1:

Intent EMail = ShareCompat.IntentBuilder.from(this)
                   .setType("message/rfc822")
                   .setSubject("Emailing: File Attached")
                   .setText("Hello")
                   .setStream(contentUri)
                   .setChooserTitle("Send via EMail").getIntent();
startActivity(Intent.createChooser(EMail, "Send via EMail"));

上面的代码向我展示了一个选择器,其中有许多可以处理文件的应用程序,如下图所示。

如果我选择任何电子邮件客户端应用程序或任何其他应用程序,这一项工作正常。

但是这样做的问题是用户可以选择任何应用程序,这不是应用程序所期望的行为。所以,我修改了如下代码:

final Intent _Intent = new Intent(Intent.ACTION_SENDTO);
_Intent.setType("text/html");
_Intent.setData(Uri.parse("mailto:"));
_Intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
_Intent.putExtra(Intent.EXTRA_STREAM, contentUri);
_Intent.putExtra(android.content.Intent.EXTRA_SUBJECT,
        "Emailing: File Attached");
_Intent.putExtra(android.content.Intent.EXTRA_TEXT,
        "Hello");
startActivity(Intent.createChooser(_Intent, "Send via EMail"));

这是代码的结果:

但是,现在的问题是我无法从内容提供者 (FileProvider) 发送文件。邮件客户端选择后显示如下消息:

它只是没有将文件附加到上述列表中任何客户端的电子邮件中。

如果有人可以在这里帮助我,我会很高兴的。我认为,我在这里尝试了所有可能的情况,通过更改 mime 类型、以不同方式设置内容设置数据设置流等,但无法获得预期的结果。

如果您需要任何其他详细信息,请告诉我。

再次提前致谢。

【问题讨论】:

  • 您需要编写 ContentProvider,它将向您传递 ContentUri 的客户端提供 InputStream。
  • @zeus 你能帮我写一两行代码吗?我在这方面有点不成熟。
  • 我不确定这是否对您有帮助,但请查看stackoverflow.com/a/31470694/3209739。 file:// 困扰了我,但没有它的工作,但它不是来自内容提供商的文件。您可以尝试没有内容:/。这是我的盲目猜测.. ;)

标签: java android email android-intent share


【解决方案1】:

试试这个 sn-p。

Intent testIntent = new Intent(Intent.ACTION_VIEW);
                    Uri data = Uri.parse("mailto:?subject=" + "Feedback" + "&body=" + "Write Feedback here....." + "&to=" + "someone@example.com");
                    testIntent.setData(data);
                    startActivity(testIntent);

【讨论】:

    【解决方案2】:

    我决定将文件从内部应用存储复制到外部应用存储(不是外部公共存储)并从那里共享文件。我有点惊讶,因为FileProvider 能够与系统中的任何事物共享内部文件存储中的文件,但是当我想过滤仅作为电子邮件客户端的 Intent 时却无法这样做。

    在初学者级别实现自定义提供程序对我来说有点困难。

    【讨论】:

      【解决方案3】:

      您需要编写 ContentProvider,它将向您传递 ContentUri 的客户端提供 InputStream,或者如果文件路径存在于 SdCard 或内部存储中,您可以直接提供文件路径,因为您需要处理uri 并传递 InputStream 。注意:ExtraStream 最适合用于从 Internet 访问的设备中不存在的文件。

      public class SampleContentProvider extends ContentProvider implements ContentProvider.PipeDataWriter<InputStream> {
      
          static final UriMatcher uriMatcher;
      
      
          static {
              uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
              //Uri matcher for different 
      
          }
      
          /**
           * Database specific constant declarations
           */
          private SQLiteDatabase db;
      
      
          @Override
          public boolean onCreate() {
              return true;
          }
      
      
          @Override
          public Uri insert(Uri uri, ContentValues values) {
      
              throw new SQLException("Insert operation not supported for  " + uri);
          }
      
          @Override
          public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
      
              //condition just for files. You can try something else
              if (uri.toString().contains("files")) {
      
                  //you get the file name
                  String lastSegment = uri.getLastPathSegment();
      
                  if (projection == null) {
                      projection = new String[]{OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE};
                  }
      
                  File file = //Code to read the file as u have the directory, just get the file from the file name obtained from the uri
      
      
                  if (null == file) {
                      throw new IllegalArgumentException("Unknown File for Uri " + uri);
                  }
                  String[] cols = new String[projection.length];
                  Object[] values = new Object[projection.length];
                  int i = 0;
                  for (String col : projection) {
                      if (OpenableColumns.DISPLAY_NAME.equals(col)) {
                          cols[i] = OpenableColumns.DISPLAY_NAME;
                          values[i++] = //file name;
                      } else if (OpenableColumns.SIZE.equals(col)) {
                          cols[i] = OpenableColumns.SIZE;
                          values[i++] = //file size;
                      }
                  }
      
                  cols = copyOf(cols, i);
                  values = copyOf(values, i);
      
                  final MatrixCursor cursor = new MatrixCursor(cols, 1);
                  cursor.addRow(values);
                  return cursor;
              }
      
              return super.query(uri, projection, selection, selectionArgs, sortOrder);
      
          }
      
          @Override
          public String getType(Uri uri) {
              return null;
          }
      
          @Override
          public int delete(Uri uri, String selection, String[] selectionArgs) {
              return super.delete(uri, selection, selectionArgs);
      
          }
      
      
          private static String[] copyOf(String[] original, int newLength) {
              final String[] result = new String[newLength];
              System.arraycopy(original, 0, result, 0, newLength);
              return result;
          }
      
          private static Object[] copyOf(Object[] original, int newLength) {
              final Object[] result = new Object[newLength];
              System.arraycopy(original, 0, result, 0, newLength);
              return result;
          }
      
          @Nullable
          @Override
          public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
      
              File file = //read the file
              if (file != null) {
                  try {
                      StrictMode.ThreadPolicy tp = StrictMode.ThreadPolicy.LAX;
                      StrictMode.setThreadPolicy(tp);   
                      InputStream in = //Code to get the inputstream;
                      // Start a new thread that pipes the stream data back to the caller.
                      return openPipeHelper(uri, null, null, in, this);
                  } catch (IOException e) {
                      FileNotFoundException fnf = new FileNotFoundException("Unable to open " + uri);
                      throw fnf;
                  }
              }
      
              throw new IllegalArgumentException("Unknown URI " + uri);
          }
      
          @Override
          public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
              return super.update(uri, values, selection, selectionArgs);
          }
      
          @Override
          public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, String mimeType,
                                      Bundle opts, InputStream args) {
              // Transfer data from the asset to the pipe the client is reading.
              byte[] buffer = new byte[8192];
              int n;
              FileOutputStream fout = new FileOutputStream(output.getFileDescriptor());
              try {
                  while ((n = args.read(buffer)) >= 0) {
                      fout.write(buffer, 0, n);
                  }
              } catch (IOException e) {
              } finally {
                  try {
                      args.close();
                  } catch (IOException e) {
                  }
                  try {
                      fout.close();
                  } catch (IOException e) {
                  }
              }
          }
      
      }
      

      【讨论】:

      • 嗨@Zeus,我想你分享给我的代码将是完成我正在寻找的事情的正确代码。但由于我无法填写您提供的代码中的空白和占位符,我将无法作证反对或支持它。感谢您提供代码。非常感谢您在这里的努力。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-12
      • 2017-09-27
      相关资源
      最近更新 更多