我找到了几个纯原生解决方案
在另一个应用程序中打开一些东西非常接近移动应用程序的系统,并且有一些事情需要考虑,这取决于平台。通常,移动应用程序在沙盒中运行,对周围系统的访问非常有限。特别是这意味着,如果您将文件下载到应用程序的沙箱中,则不允许其他应用程序(本地查看器)访问该文件。
在 Android 上,您可以将文件复制到共享空间(请参阅Application.Context.GetExternalFilesDir(null))然后打开它。使用 Essentials 可能会实现这一点,但我不太确定,但由于我们现在仍然在 Android 平台上,所以无论如何您现在都可以创建一个意图。
在 iOS 上,您可以在应用程序中创建控制器(例如,QLPreviewController 用于预览文件)以访问沙箱中的项目。根据控制器的类型(例如UIActivityViewController),他们可能会打开其他应用程序。
如何独立使用这个平台?
由于您正在编写一个独立于平台的应用程序,因此您必须注意为依赖于平台的工作调用正确的类。有几种方法可以实现这一目标
DependencyService
要使用 Xamarin.Forms DependencyService,您需要两件事
假设您有一个简单的界面来共享文件
public IShareFile
{
void ShareFile(string fileName);
}
您可以在每个平台上实现此接口的实现并将DependencyAttribute 添加到程序集。例如对于 iOS:
[assembly: Dependency(typeof(MyApp.iOS.DeviceOrientationService))]
namespace MyApp.iOS
{
public class ShareFile : IShareFile
{
public void Share(string fileName)
{
// implementation goes here
}
}
}
Android 的通用脚手架是相同的,只是实现方式不同。
使用真正的依赖注入框架
基本上是一样的。不过,您可以跳过DependencyAttribute。为了使实现可用,您必须从特定于平台的代码中获取 DI 容器,这可能很棘手。这可能是单个依赖项的过冲,但如果您仍然使用 DI 容器并且存在 X 个依赖项,那么这可能是值得的。
使用抽象基类
为你的项目添加一个抽象基类
public abstract class ShareFile
{
public static ShareFile Instance { get; protected set; }
public abstract void Share(string fileName);
}
在平台特定项目的实现中,添加一个Init() 方法
internal class ShareFileImpl : ShareFile
{
public static void Init()
{
ShareFile.Instance = new ShareFileImpl();
}
public void Share(string fileName)
{
// implementation goes here
}
}
必须从您的平台特定代码调用此 init 方法。最有可能在初始化期间。然后可以通过它的抽象从您的平台无关代码访问该实现(当然,您只会看到抽象,添加到ShareFileImpl 的公共方法不会从您的平台无关代码中可见)。
ShareFile.Instance.Share(fileName);
抽象类方法和依赖注入的组合也是可以想象的。在 DI 框架中注册您的类时,您可以像这样注册平台实例
container.RegisterInstance<ShareFile>(ShareFile.Instance);
通过这种方式,您可以利用 DI 容器功能(例如构造函数注入),同时避免在您的平台特定项目中使用 DI 容器的麻烦。缺点是,您仍然需要从您的平台特定代码中调用 ShareFileImpl.Init()。