ストレージにあるファイルを別アプリで表示、メール添付する [FileProviderの使い方]
Android7以降ではインテント(Intent)で内部ストレージにあるファイルを別アプリに投げると「FileUriExposedException」の例外が発生します。
その例外を回避するにはFileProviderクラスを使用します。
| STEP1 | AndroidManifest.xmlに「ストレージ権限」と「プロバイダ」を定義する。 |
| STEP2 | my_provider.xmlに「プロバイダで使用するpath」を定義する。 |
| STEP3 | FileProviderクラスを使用してファイルをインテントで投げます。 |
目次
1. 作るもの
2. ストレージ権限とプロバイダを定義する
3. プロバイダで使用するpathを定義する
4. コーディング
1. 作るもの
Buttonを2個、配置します。
「表示」ボタンでPDFファイルを別アプリで表示します。
「添付」ボタンでPDFファイルをメールやLINEに添付します。
※MIMEタイプを変更すればどのタイプのファイルでもOKです。
2. ストレージ権限とプロバイダを定義する
manifestsフォルダの「AndroidManifest.xml」にストレージ権限(5-6行目)とプロバイダ(23-31行目)を追加します。
[AndroidManifest.xml]
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.petitmonte.android.myapplication">
<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">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/my_provider" />
</provider>
</application>
</manifest>
3. プロバイダで使用するpathを定義する
resフォルダの上で右クリックで[新規][ディレクトリ]でxmlフォルダを作成します。
xmlフォルダの上で右クリックで[新規][XMLリソースファイル]を選択して「my_provider.xml」を作成します。
[my_provider.xml]
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="share" path="." />
</paths>
3行目でpath="."として定義しているので、内部ストレージの最階層からサブフォルダも含む全てのファイルがインテントで使用できるようになります。
外部ストレージ(SDカード)にあるファイルを使用する際には
<root-path name="sdcard" path="." />
を<paths></paths>内に追加します。
<root-path name="sdcard" path="." />
を<paths></paths>内に追加します。
4. コーディング
内部ストレージの最階層にtest.pdfファイルを設置してください。
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Environment;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import java.io.File;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 内部ストレージの最階層にあるtest.pdfファイル
// ※ファイルは各自で用意してください。
final String pathName = Environment.getExternalStorageDirectory()+"/" + "test.pdf";
// ストレージの権限の確認
if (ActivityCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) !=
PackageManager.PERMISSION_GRANTED) {
// ストレージの権限の許可を求めるダイアログを表示する
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1000);
}
// 表示
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = FileProvider.getUriForFile(MainActivity.this,
MainActivity.this.getApplicationContext().getPackageName() + ".provider",
new File(pathName));
intent.setDataAndType(uri,"application/pdf");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
try {
startActivity(intent);
}
catch (Exception e) {
e.printStackTrace();
}
}
});
// 添付
findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Uri uri = FileProvider.getUriForFile(MainActivity.this,
MainActivity.this.getApplicationContext().getPackageName() + ".provider",
new File(pathName));
Intent it = new Intent(Intent.ACTION_SEND);
it.putExtra(Intent.EXTRA_EMAIL, "");
it.putExtra(Intent.EXTRA_SUBJECT, "");
it.putExtra(Intent.EXTRA_STREAM, uri);
it.setType("application/pdf");
try {
startActivity(Intent.createChooser(it, "選択"));
}catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
スポンサーリンク
関連記事
公開日:2018年05月29日 最終更新日:2018年06月01日
記事NO:02667
プチモンテ ※この記事を書いた人
![]() | |
![]() | 💻 ITスキル・経験 サーバー構築からWebアプリケーション開発。IoTをはじめとする電子工作、ロボット、人工知能やスマホ/OSアプリまで分野問わず経験。 画像処理/音声処理/アニメーション、3Dゲーム、会計ソフト、PDF作成/編集、逆アセンブラ、EXE/DLLファイルの書き換えなどのアプリを公開。詳しくは自己紹介へ |
| 🎵 音楽制作 BGMは楽器(音源)さえあれば、何でも制作可能。歌モノは主にロック、バラード、ポップスを制作。歌詞は抒情詩、抒情的な楽曲が多い。楽曲制作は🔰2023年12月中旬 ~ | |









