拡張子に対応するアプリでファイルを開く方法 | Xamarin.Forms
- 2016/11/18
- 13:26
Android / iOS で拡張子に対応したアプリでファイルを開く方法についてご紹介いたします。
基本的に Android では Intent という仕組みがあり、MimeType を渡すことにより、対応するアプリの選択画面が表示されます。iOS では QuickLook というメジャーな拡張子に対応したビューワが存在しますので、そちらを利用します。
それぞれ、同じ開く行為なので、DependencyService にて記述します。
実行結果
Android4 / Android5 / iOS (CSVを開いた場合)



前提条件
・Windows10
・Visual Studio 2015 Community Update3
・Xamarin 4.2.0.695 以降 (NuGet Xamarin.Forms 2.3.2.127)
・macOS Sierra 10.12 以降 / Xcode8 以降
1.DependencyService にて記述します
PCLプロジェクト内にDependencyServiceで呼び出すためのインターフェースを配置します。IFileSrervice.cs
namespace AppName.Services
{
//DependencyServiceから利用する
public interface IFileService
{
void Open(string filePath, ref string err);
}
}
2.Androidの実装方法
Android プロジェクト内に拡張子に対応したアプリでファイルを開く為の以下のクラスを配置します。FileSrervice.cs
using Xamarin.Forms;
using AppName.Droid.Services;
using AppName.Services;
[assembly: Dependency(typeofFileSrervice
namespace AppName.Droid.Services
{
public class FileSrervice : IFileService
{
public void Open(string filePath, ref string err)
{
try
{
//インテント
Intent intent = new Intent();
//MimeTypeの取得
string mimetype = FileSrervice.GetMimeType(filePath);
if (String.IsNullOrEmpty(mimetype))
{
//MimeTypeが取得できなかった場合
//アクションにACTION_SENDを指定して暗黙的インテントを呼び出すことで、
//インストールされているアプリで対応可能なものが列挙されます。
mimetype = "*/*";
intent.SetAction(Intent.ActionSend);
}
else
{
//MimeTypeが取得できた場合
intent.SetAction(Intent.ActionView);
}
//URLとmimetypeを取得
Java.IO.File file = new Java.IO.File(filePath);
Android.Net.Uri uri = null;
if ((int)Build.VERSION.SdkInt < (int)(BuildVersionCodes.N))
{
//Android6.0以前
uri = Android.Net.Uri.FromFile(file);
}
else
{
//Android7.0以降
uri = Android.Support.V4.Content.FileProvider.GetUriForFile(
Forms.Context,
Forms.Context.PackageName + ".fileprovider",
file
);
}
intent.SetDataAndType(uri, mimetype);
intent.AddFlags(ActivityFlags.NewTask);
intent.AddFlags(ActivityFlags.GrantReadUriPermission | ActivityFlags.GrantWriteUriPermission);
// open
Forms.Context.StartActivity(intent);
}
catch (ActivityNotFoundException ex)
{
err = ex.Message;
}
}
}
}
※拡張子からMimeTypeを取得する方法(GetMimeType)については以下のURLにてご紹介しています。
https://itblogdsi.blog.fc2.com/blog-entry-175.html
ターゲットフレームワークを7.0以降に設定している場合は、FileProvider に関する追加の設定が必要です。次の記事「ターゲットフレームワーク Andorid7.0 以降の FileProvider の設定方法」でご紹介しておりますので、ご参考ください。
3.iOSの実装方法
iOS プロジェクト内に QuickLook に対応した拡張子のファイルを開く為に以下のクラスを配置します。まずは QuickLook にデータを受け渡しするモデルクラスを2つ作成します。
QLPreviewItemBundle.cs
using QuickLook;
public class QLPreviewItemBundle : QLPreviewItem
{
string _fileName = String.Empty;
string _filePath = String.Empty;
public QLPreviewItemBundle(string fileName, string filePath)
{
_fileName = fileName;
_filePath = filePath;
}
public override string ItemTitle
{
get
{
return _fileName;
}
}
public override NSUrl ItemUrl
{
get
{
var documents = NSBundle.MainBundle.BundlePath;
var lib = Path.Combine(documents, _filePath);
var url = NSUrl.FromFilename(lib);
return url;
}
}
}
PreviewControllerDS.cs
using QuickLook;
public class PreviewControllerDS : QLPreviewControllerDataSource
{
private IQLPreviewItem _item;
public PreviewControllerDS(IQLPreviewItem item)
{
_item = item;
}
public override nint PreviewItemCount(QLPreviewController controller)
{
return 1;
}
public override IQLPreviewItem GetPreviewItem(QLPreviewController controller, nint index)
{
return _item;
}
}
実際にファイルを開くメソッドをiOSプロジェクトに実装します。
FileSrervice.cs
using QuickLook;
using Xamarin.Forms;
using AppName.iOS.Services;
using AppName.Services;
[assembly: Dependency(typeof(FileSrervice))]
namespace AppName.iOS.Services
{
public class FileSrervice : IFileService
{
public void Open(string filePath, ref string err)
{
if (String.IsNullOrEmpty(filePath))
{
return;
}
FileInfo fi = new FileInfo(filePath);
//QuickLook
QLPreviewItemBundle prevItem = new QLPreviewItemBundle(fi.Name, fi.FullName);
QLPreviewController previewController = new QLPreviewController();
previewController.DataSource = new PreviewControllerDS(prevItem);
UINavigationController controller = FindNavigationController();
if (controller != null)
{
controller.PresentViewController(previewController, true, null);
}
else
{
UINavigationController nav = new UINavigationController(previewController);
UIApplication.SharedApplication.Windows[1].RootViewController.PresentViewController(
nav, true, null);
}
}
private UINavigationController FindNavigationController()
{
//Check to see if the rootviewcontroller is the navigationcontroller.
foreach (var window in UIApplication.SharedApplication.Windows)
{
if (window.RootViewController == null)
{
continue;
}
if (window.RootViewController.NavigationController != null)
return window.RootViewController.NavigationController;
else
{
UINavigationController val = CheckSubs(window.RootViewController.ChildViewControllers);
if (val != null)
return val;
}
}
return null;
}
private UINavigationController CheckSubs(UIViewController[] controllers)
{
foreach (var controller in controllers)
{
if (controller.NavigationController != null)
return controller.NavigationController;
else
{
UINavigationController val = CheckSubs(controller.ChildViewControllers);
if (val != null)
return val;
}
}
return null;
}
}
}
※QuickLook が対応していない拡張子は開けません。
Excel Word テキスト CSV 画像 PDF 音楽 等は対応しています。
※音楽ファイルをアプリ内で再生する場合は「音楽ファイルを再生する方法」をご参考ください。
4.使用方法
PCLプロジェクトの中の任意のページに記述します。TestPage.xaml.cs
using AppName.Services;
using Xamarin.Forms;
public partial class TestPage : ContentPage
{
async void OnFileOpenClick()
{
string err = String.Empty;
string filePath = "/file.txt";
DependencyService.Get<IFileService>().Open(filePath, ref err);
if (!String.IsNullOrEmpty(err))
{
await myPage.DisplayAlert("ファイルを開く", err, "OK");
}
}
}
当ブログの内容をまとめた Xamarin逆引きメニュー は以下のURLからご覧になれます。
https://itblogdsi.blog.fc2.com/blog-entry-81.html
- 関連記事