5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

FileProvider.GetUriForFileでハマった(Java.Lang.NullPointerException、Java.Lang.IllegalStateException)

Posted at

VIsualStudio2017, XamarinでAndroidアプリの勉強中、
FileProvider.GetUriForFileでハマりました。

##起こったエラーと解決方法

  • ####Java.Lang.NullPointerException
    providerがタグの外に出ていた。
    入れ子になっていないと読み込んでくれなかった。

  • ####Java.Lang.IllegalStateException
    SpecialFolder.Personal(内部領域)を使用しているのに、
    filepaths.xmlのタグがfiles-pathではなくexternal-pathになっていた


まず、前提として「file://~」を使った書き方はAPIが更新されていて使えないので、FileProviderを使ったやり方で実装しましょう(2019/4月)
※でも、Webのブログなどにはfileを使ったやり方がたくさんのっていて辛かった。

ちなみに、AndroidのReferenceは僕には合わなかった。
Xamarinのドキュメントが充実しているので(Androidのやきなおしだが・・・)
Xamarinを見るか、海外のフォーラムを見るのが情報が新鮮でよかったように思う。
みんなAPIとxmlの定義で苦戦していたので、どの世界も同じようだ。

sample.cs

//Androidのファイル・ディレクトリ取得
var folderPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
var fileName = folderPath + @"/sample.tsv";

/* 途中、省略 */

Android.Net.Uri uri = FileProvider.GetUriForFile(this,
                         this.ApplicationContext.PackageName+ ".provider",
                         new File(path));
filepaths.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <files-path name="share" path="." />
</resources>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="io.github.muyoku.MrTimeRecorder" android:installLocation="auto">
	<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="27" />
	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
	<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
	<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme">
		<provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true">
			<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/filepaths" />
		</provider>
	</application>
</manifest>

ちゃんとAndroidの基礎も抑えずにコード書いてせいでハマッたんだと思う。
Xamarinといっても、普段慣れ親しんだ言語出かけるだけなので、
ライフサイクルとかファイル構成とかAndroidの基礎的な思想を学んでからのほうが近道だったように思う。

特にストレージを触るなら、内部領域と外部領域の話を抑えてからのほうがいいと思う。
以下、問題解決で参考にしたサイト

★外部領域と内部領域の話 
https://docs.microsoft.com/ja-jp/xamarin/android/platform/files/

★外部、内部領域でXmlのタグ名が違う。外部の場合のみexternalで始まるものを使用する。
http://yuki312.blogspot.com/2014/04/androidfileprovider.html

・AndroidManifest、providerがapplicationタグのそとに書かれていたので参照できずヌルぽが発生
http://mo3789530.hatenablog.com/entry/2018/07/30/093434

・親切な人の解説
https://stackoverflow.com/questions/40462245/fileprovider-xamarin-not-displaying-file

・getExternalFilesDirs(外部領域からのファイルパス取得API)
https://stackoverflow.com/questions/42516126/fileprovider-illegalargumentexception-failed-to-find-configured-root

ありがとうございました。

5
5
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?