Android開発 for Kotlin 自分向けのメモ帳追加パック 動的な部分-暗黙的Intent
自分向けのメモ。たぶん新入生教育にも開発仲間にも役に立ちそう。(あくまで自分向けのsummaryだが)
動的な部分
sen-comp.hatenablog.com
暗黙的Intentとそれに係る操作
大体どころか全部ここにある。
developer.android.com
第2引数のURIが不要なものもある。
intentでのデータの受け渡しだが、非premitive型はparcelableインターフェースを実装して、getParcelableExtra<>()などを使用して受け取る。
写真撮影+保存
写真をただ撮影したいときは、第2引数のURIが不要であり、次のようなもので書ける。
//以下の定数を使う MediaStore.ACTION_IMAGE_CAPTURE val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) val requestId : Int = 334 //startActivity()すると写真撮影して得られた写真を手に入れることができない。 startActivityForResult(intent, requestId)
これは渡したintentを介在して、写真データがputExtraされている。なので、onActivityResult()をオーバーロードしてそこでリクエストコードで場合分けして処理が必要である。
具体的には、写真のデータはBitmapというデータとラベル"data"でintentに保存されている。これは、primitive型ではないので、取るにはgetParcelableExtra
val bitmap = intent.getParcelableExtra<Bitmap>("data") //このようにImageViewにセットできる。 findViewById<ImageView>(R.id.img).setImageBitmap(bitmap)
しかしこれではとても小さい画像になっていて実用性に欠ける。
より大きな画像にするには、一旦外部ストレージに保存して、それを利用する必要がある。それを達成するには次のステップを踏まなければならない。
1. 外部ストレージのアクセスの許可
2. ファイルの保存場所、名前をURIで定義
3. URIでカメラの写真の保存場所を指定してIntentでカメラを起動
外部ストレージのアクセス許可
AndroidManifest.xmlに次のことを記述。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
また、外部ストレージを利用する前に、条件分岐で当然チェックしないといけない。
if(ActivityCompat.checkSelfPermission(this@MainActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){ //ここに許可されてない場合を記述 }
ファイルの保存場所のURIの定義
AndroidのImageViewでは、URIを使って、ストレージの画像を表示することができる(setImageURI())。それ以外でも、intentのデータに適宜な定数をラベルにすることで、URIで指定した場所に勝手に保存してくれる(後述)機能もあるため、URIは必須となる。
URI自体は、次の手順で生成される。
1. ContentValuesオブジェクトの設定に必要な画像ファイル名を生成。
2. Uriオブジェクト生成に必要なContentValuesオブジェクトを生成する。
3. ContentResolverオブジェクトからUriオブジェクトを生成する。
ContentValuesオブジェクトの設定をまず行う。
まず、写真のファイル名を用意する。ファイル名の一意性の保証のしやすさの面から考えると、現在時刻を利用したファイル名がよく使われる。詳細的なコード例は以下の通り。
//日にちのフォーマットとしてはこれのほかにもいくつかある val dateFormat = SimpleDateFormat("yyyyMMddHHmmss") //Date()で現在時刻を求められる。 val now = Date() //このように文字列へ変換できる。 val nowStr : String = dateFormat.format(now) //最後にこのようなファイル名にすれば唯一性が(ほぼ確実に)担保される val fileName = "UseCameraActivityPhoto_${nowStr}.jpg"
次に、このようにして作成したファイル名fileNameを使って、URI作成に必要なContentValuesオブジェクトを生成する。ContentValues自体は、データベース系のクラスcontentResolverに値を追加するためのクラスで、Bundleみたいに値を一元的に管理できる。これからそのContentValuesに必要なデータを追加していく。ソースコード参照。
//このように作ると、空のContentValuesが作成される。 val values = ContentValues() //以下のように、ファイル名と拡張子は指定しなければならない。 values.put(MediaStore.Images.Media.TITLE, fileName) values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
ContentResolverオブジェクトからUriオブジェクトを生成
実際にURIオブジェクトを生成するのはContentResolverオブジェクトであり、これはActivityクラスの親クラスであるContextWrapperが保持しているcontextResolverとして使用される。(コード参照)これのメンバメソッドのinsert()を使用して、新たなデータの格納先を確保して、それを表すUriオブジェクトを生成してくれる。コード参照。
//第1引数の定数文字列を渡すことによって、Uriを生成される。 val _imageUri : Uri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
あとは、これをintentのExtraデータとして渡し、Intent自体にMediaStore.ACTION_IMAGE_CAPTUREを渡してActivityを開始すればよい。。
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) intent.putExtra(MediaStore.EXTRA_OUTPUT, _imageUri) startActivityForResult(intent, 200)
画像やメディアファイルの外部ストレージへの書き込みなどは以下のサイトが詳しい。
写真を撮影する | Android デベロッパー | Android Developers
外部ストレージ内のメディア ファイルを操作する | Android デベロッパー | Android Developers