将文件共享给另一个应用程序(whatsapp,telegram,gmail)

时间:2017-10-03 11:04:17

标签: c# android xamarin android-intent xamarin.android

我正在使用Xamarin.Forms开发一个Android应用程序。

到目前为止,我在开发过程中没有遇到太多困难,但现在我觉得我错过了一些东西。

我想:

  1. 从我的应用程序共享一个自定义文件(* .sl)到任何可以处理附件的应用程序(如whatsapp,telegram,gmail等)
  2. 使用我的应用
  3. 打开我的自定义文件(* .sl)

    所以,我在网上挖掘了一下并最终得到了这个;

    在我的 AndroidManifest.xml 中处理我的自定义文件

       <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.BROWSABLE" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:scheme="file" />
        <data android:host="*" />
        <data android:mimeType="*/*" />
        <data android:pathPattern=".*\.sl" />
      </intent-filter>
      <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.BROWSABLE" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:scheme="content" />
        <data android:mimeType="application/octet-stream" />
        <data android:mimeType="application/sl" />
      </intent-filter>
    

    这个类,从我的Xamarin.Forms pcl

    用作服务
    public class ShareDroid : IShare
    {
        private Context _context;
        private FileSystemExDroid _fsDroid;
    
        public ShareDroid()
        {
            _context = Android.App.Application.Context;
            _fsDroid = new FileSystemExDroid();
        }
    
        public void Show(string title, string message, string filePath)
        {
             if(!_fsDroid.FileExists(filePath))
                return;
    
            var extension = filePath.Substring(filePath.LastIndexOf(".", StringComparison.Ordinal) + 1).ToLower();
            var contentType = GetContentType(extension);
    
            var intent = new Intent(Intent.ActionSend);
            intent.SetType(contentType);
            intent.PutExtra(Intent.ExtraStream, Uri.Parse("file://" + filePath));
            intent.PutExtra(Intent.ExtraText, string.Empty);
            intent.PutExtra(Intent.ExtraSubject, message ?? string.Empty);
    
            var chooserIntent = Intent.CreateChooser(intent, title ?? string.Empty);
            chooserIntent.SetFlags(ActivityFlags.ClearTop);
            chooserIntent.SetFlags(ActivityFlags.NewTask);
            _context.StartActivity(chooserIntent);
        }
    
        private static string GetContentType(string extension)
        {
            string contentType;
    
            switch (extension)
            {
                case "pdf":
                    contentType = "application/pdf";
                    break;
                case "png":
                    contentType = "image/png";
                    break;
                case "sl":
                    contentType = "application/sl";
                    break;
                default:
                    contentType = "application/octet-stream";
                    break;
            }
    
            return contentType;
        }
    }
    

    在这里我调用我的共享服务的Show方法

    private void OnShare()
    {
        var fileSystem = DependencyService.Get<IFileSystemEx>();
        var serializer = DependencyService.Get<ISerializer>();
        var share = DependencyService.Get<IShare>();
        var fileName = $"{Name}_{Id}.sl";
        var path = fileSystem.CreateFilePath(fileName, SpecialFolder.Personal);
        serializer.Save(path, Model);
        share.Show(Resources.ShareViaLabel, Resources.ShareViaMessage, path);
    }
    

    当我在任何设备上测试应用程序(未模拟)时,我得到相同的结果。

    • Gmail说&#34;附件权限被拒绝&#34;
    • WhatsApp和Telegram表示&#34;附件不受支持&#34;

    Resources.ShareViaMessage(这是一个小描述)可以毫无问题地打印在目标应用程序中。

    自定义文件实际上是一个带有自定义扩展名(.sl)的.txt文件。

    任何人都可以提供帮助吗?

1 个答案:

答案 0 :(得分:1)

最后我想出了一个解决方案。 我从清单中删除了意图,并在主活动中对它们进行编码,如下所示:

[IntentFilter(
new[] { Intent.ActionView }, 
Categories = new [] { Intent.CategoryBrowsable, Intent.CategoryDefault }, 
DataMimeType = "text/plain",
DataPathPatterns = new []
{
    @".*\\.sl",
    @".*\\..*\\.sl",
    @".*\\..*\\..*\\.sl",
    @".*\\..*\\..*\\..*\\.sl"
})]
[IntentFilter(
new[] { Intent.ActionSend },
Categories = new[] { Intent.CategoryBrowsable, Intent.CategoryDefault },
DataMimeType = "text/plain",
DataPathPatterns = new []
{
    @".*\\.sl",
    @".*\\..*\\.sl",
    @".*\\..*\\..*\\.sl",
    @".*\\..*\\..*\\..*\\.sl"
})]

还更改了 Share.Show 方法以使用来自fileprovider的uri:

public void Show(string title, string filePath)
    {
        if(!_fsDroid.FileExists(filePath))
            return;

        var fileUri = FileProvider.GetUriForFile(_context, "com.***********.******.fileprovider", new File(filePath));
        var intent = new Intent(Intent.ActionSend);
        intent.SetType("text/plain");
        intent.PutExtra(Intent.ExtraText, string.Empty);
        intent.PutExtra(Intent.ExtraStream, fileUri);
        intent.SetData(fileUri);
        intent.SetFlags(ActivityFlags.GrantReadUriPermission);
        intent.SetFlags(ActivityFlags.ClearTop);
        intent.SetFlags(ActivityFlags.NewTask);

        var chooserIntent = Intent.CreateChooser(intent, title ?? string.Empty);
        _context.StartActivity(chooserIntent);
    }

在清单中,在应用程序标记内添加了

  <provider android:name="android.support.v4.content.FileProvider" android:authorities="com.***********.******.fileprovider" android:exported="false" android:grantUriPermissions="true">
    <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" />
  </provider>

这是我的 file_paths.xml

的内容
<paths xmlns:android="http://schemas.android.com/apk/res/android">
  <files-path name="exports" path="exports/"/>
</paths>

现在我的应用程序导出.sl文件,whatsapp,telegram,gmail和任何其他支持text / plain文件的应用程序都接受附件。

此外,在打开/发送.sl文件时,我的应用程序已列出并可用作此类文件的默认值。

希望将来帮助其他人:)