Closed5

Android標準のビューアでPDFを開きたい

Yuya MimuraYuya Mimura

まずAndroid標準のビューアでPDFを開く記事(どのアプリで開くか選択させる)
後でやってみる

val target = Intent(Intent.ACTION_VIEW)
target.apply {
  setDataAndType(Uri.fromFile(pdfFile),"application/pdf")
  setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
}
val intent = Intent.createChooser(target, "Open File")
try {
    startActivity(intent);
} catch (e) {
    // Instruct the user to install a PDF reader here, or something
}   

https://stackoverflow.com/a/17453242

Yuya MimuraYuya Mimura

なんか上手くいかないので、画像として表示してみる。

val parcelFileDescriptor = ParcelFileDescriptor.open(pdfFile, ParcelFileDescriptor.MODE_READ_ONLY)
val pdfRenderer = PdfRenderer(parcelFileDescriptor)
// とりあえず1ページ目だけ
val page = pdfRenderer.openPage(0)
val bitmap = Bitmap.createBitmap(page.width, page.height, Bitmap.Config.ARGB_8888)
page.render(bitmap, Rect(0, 0, page.width, page.height), null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)

val imageFos = FileOutputStream(imagePath)
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, imageFos)

imageFos.flush()
imageFos.close()

page.close()
pdfRenderer.close()

val imageFile = File(imagePath)
Yuya MimuraYuya Mimura
val target = Intent(Intent.ACTION_VIEW)
target.apply {
  setDataAndType(Uri.fromFile(imageFile),"image/jpg")
  setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
}
val intent = Intent.createChooser(target, "Open File")
try {
    startActivity(intent);
} catch (e) {
}   

これをすると、トーストで「ファイル形式は現在サポートされていません」と表示される。普通に撮影した画像は表示されるのでサポートされてないはずはない。

Yuya MimuraYuya Mimura

Device File Explorerで確認すると画像自体は書き出せている。
Uri.fromFileでうまくファイルが読めていないのでは?と思い調べてみると、FileProviderを利用したFile Uriの取得方法があった。(今更)
https://qiita.com/PET_HAL/items/ea4441a8adf56b4c380a

今回はcacheDirに画像を保存していたので、cache-path要素を持ったpaths.xmlを追加

app/res/xml/paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <cache-path
        name="files"
        path="." />
</paths>

AndroidManifest.xmlにもproviderの記載を追加

app/src/main/AndroidManifest.xml
    <application
       ...
        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/paths" />
        </provider>
      </application>

FileProviderクラスを使った実装に修正

val uri = 
  FileProvider.getUriForFile(requireContext(), "${BuildConfig.APPLICATION_ID}.fileprovider", imageFile)

これをすると、一瞬何か別アプリが立ち上がるがすぐに閉じる、みたいな挙動になった

Yuya MimuraYuya Mimura

下記の記事を参考に、元のコードから

  • Intent.flagsをIntent.FLAG_GRANT_READ_URI_PERMISSIONに変更
  • createChooserをやめる

とPDFファイルのままで標準のビューアが立ち上がった。

https://stackoverflow.com/questions/31621419/android-how-do-i-open-a-file-in-another-app-via-intent

最終的なコード

val target = Intent(Intent.ACTION_VIEW)
val uri =
     FileProvider.getUriForFile(requireContext(), "${BuildConfig.APPLICATION_ID}.fileprovider", pdfFile)
val mime = requireContext().contentResolver.getType(uri)

target.setDataAndType(uri, mime)
target.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION

startActivity(target)
このスクラップは2022/02/20にクローズされました