LoginSignup
14
19

More than 5 years have passed since last update.

Android端末のDCIMに保存してギャラリーで表示させる方法

Posted at

検証環境

この記事の内容は、以下の環境で検証しました。

  • Java:open jdk 1.8.0_152
  • Kotlin 1.2.0
  • Android Studio 3.0.2
  • CompileSdkVersion:26
  • MinSdkVersion:21
  • TargetSdkVersion:26
  • BuildToolsVersion:26.0.2
  • gradle:4.0.0

目標

本記事では、以下の2点を目標としています。
* アプリ内で画像をDCIMに保存する
* 保存した画像をギャラリーに表示させる

アプリの動き

この記事で作成するアプリは、下記の仕様になっています。

Untitled.png

ファイル構成

この記事で作成するアプリは下記のファイルで構成しています。

ファイル名 説明
AndroidManifest.xml マニフェストファイル
layout/activity_main.xml 画面のレイアウト
jp.co.casareal.filetodcim.MainActivity ファイルの保存処理が記載されているActivity
drawable/pic.png サンプル画像

画像をDCIMに保存する

AndroidManifest.xml

コード

DCIMは外部ストレージの扱いになるため、外部ストレージへのパーミッションを追記します。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="jp.co.casareal.filetodcim">
    <uses-permission
        android:name="android.permission.WRITE_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>
    </application>
</manifest>

activity_main.xml

コード

保存するためのボタンと、保存する画像のサンプルを表示するImageViewを配置しています。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">


    <Button
        android:id="@+id/btn_save"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="下記の画像をDCIMに保存" />

    <ImageView
        android:src="@drawable/pic"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

jp.co.casareal.filetodcim.MainActivity

コード

本記事のコードでは、下記の処理を実装しています。

  • 外部ストレージへの書き込み権限を取得するために、ダイアログを表示しています。
  • 外部ストレージのパスを取得し、Fileクラスを生成します。
  • BitmapFactoryを利用してpic.jpegを読み込み、DCIMに保存します。
  • ギャラリーからもアクセス出来るように、画像データとしてAndroidに登録します。

コードの全体像

package jp.co.casareal.filetodcim

import android.Manifest
import android.content.ContentValues
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Bundle
import android.os.Environment
import android.provider.MediaStore
import android.support.v4.app.ActivityCompat
import android.support.v4.content.ContextCompat
import android.support.v7.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import java.io.File
import java.io.FileOutputStream

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    override fun onResume() {
        super.onResume()

        btn_save.setOnClickListener {
            if (ContextCompat.checkSelfPermission(applicationContext, Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED) {
                ActivityCompat.requestPermissions(this,
                        arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
                        1)
            } else {
                saveFile(createFile())
            }
        }
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        // 絶対に許可される前提で記述
        saveFile(createFile())
    }

    private fun createFile(): File {
        val dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)

        return File(dir, "pic.jpeg")
    }

    private fun saveFile(f: File) {

        val bit = BitmapFactory.decodeResource(resources, R.drawable.pic)

        val ops = FileOutputStream(f)

        bit.compress(Bitmap.CompressFormat.PNG, 100, ops)

        ops.close()

        val contentValues = ContentValues().apply {
            put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
            put("_data", f.absolutePath)
        }

        contentResolver.insert(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)

    }
}

外部ストレージへの書き込み権限を取得するためのダイアログ表示

 ActivityCompat.requestPermissions(this,
                        arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
                        1)

外部ストレージのパスを取得し、Fileクラスの生成

    private fun createFile(): File {
        val dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)

        return File(dir, "pic.jpeg")
    }

BitmapFactoryを利用してpic.jpegを読み込み、DCIMに保存

        val bit = BitmapFactory.decodeResource(resources, R.drawable.pic)

        val ops = FileOutputStream(f)

        bit.compress(Bitmap.CompressFormat.PNG, 100, ops)

        ops.close()

ギャラリーからもアクセス出来るように、画像データとしてAndroidに登録

        val contentValues = ContentValues().apply {
            put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
            put("_data", f.absolutePath)
        }

        contentResolver.insert(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)

もう一つ方法があります。ブロードキャストでOSに今一度スキャンをさせるという方法です。
ただし、アプリ内のフォルダに画像を保存した場合は、対象にならないので保存する場所に注意が必要です。

        val mediaScanIntent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)
        val contentUri = Uri.fromFile(f)
        mediaScanIntent.data = contentUri
        this.sendBroadcast(mediaScanIntent)
14
19
0

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
14
19