カメラ実装用アクティビティ追加
(1) メニューから「ファイル」-「新規」-「アクティビティー」-「空のアクティビティー」を選択します。
(2) 以下を入力し、完了ボタンをクリックします。
- アクティビティー名 :LiveCamera
- レイアウト・ファイルを生成する :チェックする
- ソース言語 :Kotlin
- ターゲット・ソース・セット :main
MainActivityのレイアウト変更
(1) プロジェクトツリーから app/res/layout/activity_main.xml をダブルクリックします。
(2) パレットの「Buttons」を選択、「Button」を画面上にドラッグします。
※この画面が表示されていないときは「※ここをクリック!」をクリックしてください。
以下を設定してください。
- id :takeVideoBtn
- text : カメラ起動
(3) コンポーネント・ツリーの「takeVideoBtn」にエラー表示のアイコンがあるとき、画面上部の①のアイコンをクリックし、エラーを除去します。
Ctrl+sで保存します。
LiveCameraActivityのレイアウト変更
(1) プロジェクトツリーから app/res/layout/activity_live_camera.xml をダブルクリックします。
(2) 画面右上の「コード」アイコンをクリックします。
(3) 以下のコードを入力し、Ctrl+sで保存します。
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".LiveCamera"> <VideoView android:id="@+id/videoView" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginBottom="57dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
プログラム修正
(1) プロジェクトツリーから app/manifests/AndroidManifest.xml をダブルクリックします。
(2) 以下のコードを入力し、Ctrl+sで保存します。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.livecamera"> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.hardware.camera.autofocus" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.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=".LiveCamera" android:parentActivityName=".MainActivity"> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".MainActivity" /> </activity> <meta-data android:name="com.google.firebase.ml.vision.DEPENDENCIES" android:value="face" /> <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>
(3) プロジェクトツリーから app/java/com.example.livecamera/MainActivity をダブルクリックします。
(4) 以下のコードを入力し、Ctrl+sで保存します。
package com.example.livecamera import android.Manifest import android.content.Intent import android.content.pm.PackageManager import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.widget.Button import android.widget.Toast import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat class MainActivity : AppCompatActivity() { companion object { const val CAMERA_PERMISSION_REQUEST_CODE = 2 } private lateinit var takeVideoBtn: Button override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) takeVideoBtn = findViewById(R.id.takeVideoBtn) } override fun onResume(){ super.onResume() takeVideoBtn.setOnClickListener{ // カメラ機能を実装したアプリが存在するかチェック val intent = Intent(applicationContext, LiveCamera::class.java) intent.resolveActivity(packageManager)?.let { if (checkCameraPermission()) { startActivity(intent) } else { grantCameraPermission() } } ?: Toast.makeText(this, "カメラを扱うアプリがありません", Toast.LENGTH_LONG).show() } } private fun grantCameraPermission() = ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), CAMERA_PERMISSION_REQUEST_CODE) private fun checkCameraPermission() = PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(applicationContext, Manifest.permission.CAMERA) }
(5) プロジェクトツリーから app/java/com.example.livecamera/LiveCamera をダブルクリックします。
(6) 以下のコードを入力し、Ctrl+sで保存します。
package com.example.livecamera import android.content.Intent import android.net.Uri import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.os.Environment.DIRECTORY_MOVIES import android.provider.MediaStore import android.widget.VideoView import java.io.File import java.io.IOException class LiveCamera : AppCompatActivity() { private lateinit var videoView: VideoView private var capturedUri: Uri? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_live_camera) videoView = findViewById(R.id.videoView) takeVideo() } private fun takeVideo(){ dispatchTakeVideoIntent() videoView.setVideoURI(intent.data) videoView.start() } private fun dispatchTakeVideoIntent() { val takeVideoIntent = Intent(MediaStore.ACTION_VIDEO_CAPTURE) takeVideoIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) if (takeVideoIntent.resolveActivity(packageManager) != null) { try { takeVideoIntent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 10) takeVideoIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1) val videoFile: File = createMediaFile() println("=============>videoFile = $videoFile") capturedUri = Uri.fromFile(videoFile) takeVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, capturedUri) startActivityForResult(takeVideoIntent, 200) } catch (e: IOException) { e.printStackTrace() } } } private fun createMediaFile(): File { // Create an image file name val fileName = "VID_" val directory:File = File(System.getProperty("java.io.tmpdir", ".") + "/" + DIRECTORY_MOVIES) if (!directory.exists()) directory.mkdir() return File("$directory/$fileName${System.currentTimeMillis()}.mp4") } }
実行
(1) メニューの「ビルド」-「プロジェクトの再ビルド」をクリックします。
(2) ステータスバーに進行状況が表示され、「ビルド出力」と「イベント・ログ」でビルドエラーなどの確認ができます。
(3) ビルドが終了するとステータスバーに「Gradleビルドが完了しました」が表示されます。
「ビルド出力」に BUILD SUCCESSFUL が表示されていることを確認します。
(4) デバッグする実機が「SHARP SH-05G」であることを確認し、「実行」アイコンをクリックします。
(5) ステータスが以下の順に表示され、実機にインストールされます。
(6) 実機で作成したアプリが実行されています。
個人的感想
分かったこと
- Activity の命名を「~Activity」にしなかったため、プロジェクト名なのかアクティビティなのか分からなくなった
- Activity から Intent を生成して 別Activityを呼び出す
- Intentしてカメラを使う
- 表示するものと用途によってViewを使い分ける必要がある
- onResumeなど、割り込み関係を overrideする
- ローカルストレージのアクセス方法
- Toastが楽しい!
分からなかったこと
- Manifest の 中身
- permissionが正しく出来ているのかわからない
- カメラ制御が古いロジック?(camera2でない)
- androidバージョン違いの他の端末で動くのか?
- カメラ終了してないので、最初の画面に戻らずハングったりする。
端末再起動しないとカメラが使えなくなる。