使用 Android 使用 Microsoft Office 移动应用程序以编辑模式打开本地文件

Opening local files in edit mode with Microsoft Office mobile app using Android

我正在开发一个 Android 应用程序,我想从该应用程序启动 MS Office 应用程序来查看和编辑 Office 文件。例如,打开存储在设备本地的 docx,以便在 MS-Word 移动应用程序中进行编辑。

以前,我们打开此类文件时会使用在意图中传递的文件 URI,例如"com.microsoft.office.word" 包名称。该文件将在 Word for Android 中打开,用户可以对其进行编辑和保存。没问题。

现在我们必须进行更改,以便我们使用具有读写权限的 Android 的 FileProvider 类。通过此实施,其他应用程序可以编辑文件,但适用于 Android 的 Microsoft Office 应用程序以只读模式打开,无法更改它。

这似乎是其他人也会遇到的常见问题,如其他 stackoverflow 问题所示:

使用 Android 文件提供程序时,尽管在意图中标记了 FLAG_GRANT_WRITE_URI_PERMISSION,但文件没有正确的权限

Xamarin.Forms Android FileProvider:GrantWriteUriPermission 并不总是有效

我还找到了这个链接,其中包含有关如何在 msdn 中调用 office 应用程序的信息,但它似乎很不完整,我无法使其与意图和本地文件一起工作(我只是不\\ '不知道如何发送 ms-word:ofe|u|file 以便它识别它,它总是抱怨它找不到文件)。

有谁知道使用 FileProvider 从 microsoft office for Android 中的 android 应用程序以编辑模式打开本地文件的方法?

我没有发布任何代码,因为它没有问题。任何其他应用都可以正常工作,但 Microsoft Office 应用除外。


我编写了一个通用的打开例程,然后分解出单个文件类型,如下所示。执行以下操作后我没有遇到问题。希望这会有所帮助。 (注意 - 我只添加了单词 call - 但在这里使用 SO 文章中的类型(docx、pptx 等的正确 mime 类型是什么?)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
public static Java.IO.File CopyDocuments(Java.IO.File source, string realName)
{

    //string path = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments); <-- old method
    string path = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).AbsolutePath;
    if (!System.IO.Directory.Exists(Path.Combine(path,"appname")))
        System.IO.Directory.CreateDirectory(Path.Combine(path,"appname"));

    string dbPath = Path.Combine(path,"appname", realName);
    Java.IO.File destination = new Java.IO.File(dbPath);

    try
    {
        //if (destination.Exists())
        //    destination.Delete();

        if (!destination.Exists())
        {
            using (FileStream fs = new FileStream(source.AbsolutePath, FileMode.Open, FileAccess.Read))
            {
                using (var br = new BinaryReader(fs))
                {
                    using (var bw = new BinaryWriter(new FileStream(dbPath, FileMode.Create)))
                    {
                        byte[] buffer = new byte[2048];
                        int length = 0;
                        while ((length = br.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            bw.Write(buffer, 0, length);
                        }
                    }
                }
            }
        }

        return destination;
    }
    catch (Exception ex)
    {
        Toast.MakeText(Xamarin.Forms.Forms.Context,"Error Copying:" + ex.Message, ToastLength.Long).Show();
    }
    return null;
}

public void LaunchApp(string fileLocation, string realName)
{
    var file = new Java.IO.File(fileLocation);

    if (!file.Exists())
        return;

    file = CopyDocuments(file, realName);

    Intent intent = null;
    var extension = System.IO.Path.GetExtension(fileLocation).ToLower();

    switch (extension)
    {
        case ContentService.DocxExtension:
            intent = ReturnWord(file, true);
            break;
        case ContentService.DocExtension:
            intent = ReturnWord(file, false);
            break;
        case ContentService.TxtExtension:
        case PlayerLync.Services.ContentService.RtfExtension:
            intent = ReturnText(file);
            break;
        case ContentService.XlsExtension:
            intent = ReturnExcel(file, false);
            break;
        case ContentService.XlsxExtension:
            intent = ReturnExcel(file, true);
            break;
        case ContentService.PPExtension:
            intent = ReturnPowerPoint(file, false);
            break;
        case ContentService.PPXExtension:
            intent = ReturnPowerPoint(file, true);
            break;
        case ContentService.Mp3Extension:
            //contentType = ContentType.Audio;
            break;
        default:
            //contentType = ContentType.Unknown;
            break;
    }

    try
    {
        Xamarin.Forms.Forms.Context.StartActivity(intent);
    }
    catch (Exception ex)
    {
        ... log error
    }
}

private Intent ReturnWord(Java.IO.File file, bool isEx)
{
    var intent = new Intent(Intent.ActionView);
    Android.Net.Uri uri = FileProvider.GetUriForFile(Xamarin.Forms.Forms.Context,"your_package.fileprovider", file);// --> old method Android.Net.Uri.FromFile(file); //
    intent.AddFlags(ActivityFlags.GrantReadUriPermission);
    intent.AddFlags(ActivityFlags.GrantWriteUriPermission);
    intent.AddFlags(ActivityFlags.GrantPersistableUriPermission);
    intent.PutExtra(Intent.ExtraStream, uri);
    if (!isEx)
    {
        intent.SetDataAndType(uri,"application/vnd.msword");
    }
    else
    {
        intent.SetDataAndType(uri,"application/vnd.openxmlformats-officedocument.wordprocessingml.document");
    }
    return intent;
}

将这一切都放在 Android 项目中并执行自定义渲染器以从 Xamarin Forms 访问它