Closed nsaito92 closed 4 years ago
対応開始。
ざっくり必要と思う機能
対応する順番
アラームに使用する音楽ファイルをユーザーに選ばせる機能
まずは、上記でどこまで外部アプリに任せられるか調べる。 それ次第で実装する量が変わるため。 こちらの対応の様に自前の画面で、一覧を表示することもできるが、 出来れば、他アプリに任せたい。
MediaPlayer#setDataSource
で、AssetFileDescriptor
で取得したFileDescriptor
(resディレクトリのmp3ファイル)を、リソースデータとして渡している。FileDescriptor
オブジェクトとして渡せる様になることが、単純に考えるとまず必要そう。
FileOutputStream#getFD
でFileDescriptor
を渡すことが出来る。MediaStore API
でもいけそうFileProvider
openFileInput
関数で、読み出すファイルを取得。FileInputStream
クラスに、openFileInputの戻り値を指定して、インスタンス作成。InputStreamReader
インスタンスに、FileInputStreamインスタンスと、****パラメータとして、インスタンス作成。BufferedReader
インスタンスを、InputStreamReaderを元に作成。FileInputStream
から生成するFileOutputStream
から生成するFileDescriptor
を作成する。File
またはにデータを書き込むための出力ストリーム。FileWriter
などの別APIの使用を検討する。08-17 00:11:57.578 11804-11804/org.bitbucket.snaoto22.frock D/AlarmPreferenceActivity: intent.getData = content://com.android.externalstorage.documents/document/primary%3AAndroid%2Fmedia%2Fcom.Slack%2FNotifications%2FSlack%20-%20Boing.mp3
08-17 00:12:27.604 11804-11804/org.bitbucket.snaoto22.frock D/AlarmPreferenceActivity: intent.getData = content://com.android.externalstorage.documents/document/0000-0000%3Asu650.mp3
08-17 00:15:19.023 11804-11804/org.bitbucket.snaoto22.frock D/AlarmPreferenceActivity: intent.getData = content://com.google.android.apps.docs.storage/document/acc%3D2%3Bdoc%3Dencoded%3D%2B1fR89%2BRCEobm2lJHkODumwbONticCy%2BBkdcQSse8X1%2BgTAfanKj
am start -a android.intent.action.VIEW -d https://techbooster.org/
am start -a android.intent.action.OPEN_DOCUMENT -c android.intent.category.OPENABLE -t "image/*"
am start -a android.intent.action.OPEN_DOCUMENT_TREE -c android.intent.category.OPENABLE -t "image/*"
am start -a android.intent.action.OPEN_DOCUMENT -c android.intent.category.OPENABLE -t "audio/*"
/**
* ContentResolverを使用して、URIから正確なファイルパスを取得する。
* @param uri
* @return
*/
public String getFilePathFromUri(Uri uri) {
Log.d(TAG, "getFilePathFromUri");
Log.d(TAG, "uri = " + uri);
Cursor cursor = null;
String filepath = null;
String[] columns = {MediaStore.Audio.Media.DATA}; // ★この変数は不要とする。
Log.d(TAG, "columns[0] = " + columns[0]);
try {
cursor = contentResolver.query(uri, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
// ここには入ってくる
Log.d(TAG, "cursor OK");
// カウントは1とれるので、データが一つ取れている。
Log.d(TAG, "cursor.getCount() = " + cursor.getCount());
// ★データを取得すると、null。 → queryのprojectionにcolumnsを指定するのをやめたところ、取得出来た。
// URLが分かって入ればprojectionを指定する理由がないと思われるので、こちらはnullで検討を進める。
Log.d(TAG, "cursor.getString(0) = " + cursor.getString(0));
filepath = cursor.getString(0);
}
} finally {
cursor.close();
}
Log.d(TAG, "filepath = " + filepath);
return filepath;
}
結果 ディレクトリが参照できていない。
08-23 18:36:57.998 2094-2094/org.bitbucket.snaoto22.frock D/ContentResolverController: getFilePathFromUri
08-23 18:36:57.998 2094-2094/org.bitbucket.snaoto22.frock D/ContentResolverController: uri = content://com.android.externalstorage.documents/document/primary%3AAndroid%2Fmedia%2Fcom.Slack%2FNotifications%2FSlack%20-%20Boing.mp3
08-23 18:36:57.998 2094-2094/org.bitbucket.snaoto22.frock D/ContentResolverController: columns[0] = _data
08-23 18:36:58.016 2094-2094/org.bitbucket.snaoto22.frock D/ContentResolverController: cursor OK
08-23 18:36:58.016 2094-2094/org.bitbucket.snaoto22.frock D/ContentResolverController: cursor.getCount() = 1
08-23 18:36:58.017 2094-2094/org.bitbucket.snaoto22.frock D/ContentResolverController: cursor.getString(0) = primary:Android/media/com.Slack/Notifications/Slack - Boing.mp3
08-23 18:36:58.018 2094-2094/org.bitbucket.snaoto22.frock D/ContentResolverController: filepath = primary:Android/media/com.Slack/Notifications/Slack - Boing.mp3
08-23 18:36:58.019 2094-2094/org.bitbucket.snaoto22.frock W/System.err: java.io.FileNotFoundException: primary:Android/media/com.Slack/Notifications/Slack - Boing.mp3 (No such file or directory)
こちらの記事を参考にした。
public String getFilePathFromUri(Uri uri) {
Log.d(TAG, "getFilePathFromUri");
Log.d(TAG, "uri = " + uri);
String filepath = null;
// URIにより、取得方法が異なるため処理を分ける。
if (ClockUtil.PackageNames.COM_ANDROID_EXTERNALSTORAGE_DOCUMENTS.
equals(uri.getAuthority())) {
Log.d(TAG, "uri.getAuthority() = " + uri.getAuthority());
//
String docID = DocumentsContract.getDocumentId(uri);
String split[] = docID.split(":");
String type = split[0];
Log.d(TAG, "type = " + type);
Log.d(TAG, "split[1] = " + split[1]);
//
if ("primary".equalsIgnoreCase(type)) {
Log.d(TAG, "test : 1");
filepath = Environment.getExternalStorageDirectory() + "/" + split[1];
} else {
Log.d(TAG, "test : 2");
//
filepath = "/stroage/" + type + "/" + split[1];
}
} else {
Log.d(TAG, "test : 3");
Cursor cursor = null;
String[] columns = {MediaStore.Audio.Media.DATA}; // ★この変数は不要とする。
Log.d(TAG, "columns[0] = " + columns[0]);
try {
cursor = contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
// ここには入ってくる
Log.d(TAG, "cursor OK");
// カウントは1とれるので、データが一つ取れている。
Log.d(TAG, "cursor.getCount() = " + cursor.getCount());
// ★データを取得すると、null。 → queryのprojectionにcolumnsを指定するのをやめたところ、取得出来た。
// URLが分かって入ればprojectionを指定する理由がないと思われるので、こちらはnullで検討を進める。
Log.d(TAG, "cursor.getString(0) = " + cursor.getString(0));
filepath = cursor.getString(0);
}
} finally {
if (cursor != null) {
cursor.close();
}
}
}
Log.d(TAG, "filepath = " + filepath);
return filepath;
}
結果 権限がないと言われている。
08-24 01:17:56.377 10043-10043/org.bitbucket.snaoto22.frock D/ContentResolverController: getFilePathFromUri
08-24 01:17:56.377 10043-10043/org.bitbucket.snaoto22.frock D/ContentResolverController: uri = content://com.android.externalstorage.documents/document/primary%3AAndroid%2Fmedia%2Fcom.Slack%2FNotifications%2FSlack%20-%20Boing.mp3
08-24 01:17:56.377 10043-10043/org.bitbucket.snaoto22.frock D/ContentResolverController: uri.getAuthority() = com.android.externalstorage.documents
08-24 01:17:56.379 10043-10043/org.bitbucket.snaoto22.frock D/ContentResolverController: type = primary
08-24 01:17:56.379 10043-10043/org.bitbucket.snaoto22.frock D/ContentResolverController: split[1] = Android/media/com.Slack/Notifications/Slack - Boing.mp3
08-24 01:17:56.379 10043-10043/org.bitbucket.snaoto22.frock D/ContentResolverController: test : 1
08-24 01:17:56.383 10043-10043/org.bitbucket.snaoto22.frock D/ContentResolverController: filepath = /storage/emulated/0/Android/media/com.Slack/Notifications/Slack - Boing.mp3
08-24 01:17:56.386 10043-10043/org.bitbucket.snaoto22.frock W/System.err: java.io.FileNotFoundException: /storage/emulated/0/Android/media/com.Slack/Notifications/Slack - Boing.mp3 (Permission denied)
権限追加して、端末上で酒毒で権限追加。
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
結果 FileDescriptorオブジェクトの生成に成功出来た。
08-24 01:42:44.194 14783-14783/org.bitbucket.snaoto22.frock D/ContentResolverController: getFilePathFromUri
08-24 01:42:44.194 14783-14783/org.bitbucket.snaoto22.frock D/ContentResolverController: uri = content://com.android.externalstorage.documents/document/primary%3AAndroid%2Fmedia%2Fcom.Slack%2FNotifications%2FSlack%20-%20Boing.mp3
08-24 01:42:44.194 14783-14783/org.bitbucket.snaoto22.frock D/ContentResolverController: uri.getAuthority() = com.android.externalstorage.documents
08-24 01:42:44.196 14783-14783/org.bitbucket.snaoto22.frock D/ContentResolverController: type = primary
08-24 01:42:44.196 14783-14783/org.bitbucket.snaoto22.frock D/ContentResolverController: split[1] = Android/media/com.Slack/Notifications/Slack - Boing.mp3
08-24 01:42:44.196 14783-14783/org.bitbucket.snaoto22.frock D/ContentResolverController: test : 1
08-24 01:42:44.198 14783-14783/org.bitbucket.snaoto22.frock D/ContentResolverController: filepath = /storage/emulated/0/Android/media/com.Slack/Notifications/Slack - Boing.mp3
08-24 01:42:44.199 14783-14783/org.bitbucket.snaoto22.frock D/AlarmPreferenceActivity: inputStream.getFD() = java.io.FileDescriptor@9c62f40
間が空いてしまったので現状整理
MediaPlayer#setDataSource
に渡すFileDescriptor
を他アプリから取得する方法の仮実装が出来た。FrockSettingsOpenHelper
AlarmSettingEntity
FrockSettingsHelperController
AlarmService
ClockUtil
AlarmPreferenceActivity
新規作成したカラムにデータ追加、修正、削除が行えることを確認。
sqlite> select * from alarmsettingsdb;
1|1|1|12|1,4,5|content://com.android.externalstorage.documents/document/primary%3AAndroid%2Fmedia%2Fcom.Slack%2FNotifications%2FSlack%20-%20Boing.mp3
2|0|1|21|1,5|content://com.android.externalstorage.documents/document/primary%3AAndroid%2Fmedia%2Fcom.Slack%2FNotifications%2FSlack%20-%20Plink.mp3
sqlite>
カラムの追加をしたので、テーブルの再作成を行いたかったが、 アプリをアンインストールしても、DBが消えなかった件。 マニフェストのAndroid:allowBackupの設定の問題だった。
android:allowBackup
アプリがバックアップ / 復元用インフラストラクチャに参加できるようにするかどうかを指定します。この属性を false に設定した場合、すべてのアプリデータを保存するフルシステム バックアップを adb 経由で実行したとしても、このアプリのバックアップや復元は行われません。この属性のデフォルト値は true です。
sqlite> .tables
alarmsettingsdb android_metadata
sqlite> select * FROM alarmsettingsdb;
1|1|1|12|1,4,5|content://com.android.externalstorage.documents/document/primary%3AAndroid%2Fmedia%2Fcom.Slack%2FNotifications%2FSlack%20-%20Boing.mp3
2|0|1|21|1,5|content://com.android.externalstorage.documents/document/primary%3AAndroid%2Fmedia%2Fcom.Slack%2FNotifications%2FSlack%20-%20Plink.mp3
sqlite>
* 次に永続化した情報を元に、アラームサービスにセットする処理を作り込む。(ド正常系)
* それが出来たら、非正常系、異常系処理を対応。
考えてなかった点
AlarmService
からDBのURIを参照する処理を追加するが、どの行のデータを参照すれば分からない状態だった。AlarmService
インスタンス生成時に元になる行情報を、Intentで渡す様にすることを検討する。進捗
1
を渡して、DBクエリで音楽ファイルを使用して再生する処理を実装。進捗
■対応したこと
■見えている課題
■別チケット
97a8192919235d18765f1a012fbc3eb97da5ec30 の単体試験。
ファイル選択を行なったが、読み取れないURIだった。まだ「保存」ボタンは押していないため、前のデータが保存されたままの状態。
sqlite> select * FROM alarmsettingsdb;
1|1|7|15|1,2,3,4,5|content://com.android.externalstorage.documents/document/primary%3AAndroid%2Fmedia%2Fcom.Slack%2FNotifications%2FSlack%20-%20Incoming%20call.mp3
2|1|16|50|1,2,3,4,5|content://com.android.externalstorage.documents/document/primary%3AAndroid%2Fmedia%2Fcom.Slack%2FNotifications%2FSlack%20-%20Plink.mp3
3|1|18|19|4|content://com.android.externalstorage.documents/document/primary%3AAndroid%2Fmedia%2Fcom.Slack%2FNotifications%2FSlack%20-%20Wow.mp3
保存ボタンタップ後。無効なデータである情報を保存した。
sqlite> select * FROM alarmsettingsdb;
1|1|7|15|1,2,3,4,5|content://com.android.externalstorage.documents/document/primary%3AAndroid%2Fmedia%2Fcom.Slack%2FNotifications%2FSlack%20-%20Incoming%20call.mp3
2|1|16|50|1,2,3,4,5|content://com.android.externalstorage.documents/document/primary%3AAndroid%2Fmedia%2Fcom.Slack%2FNotifications%2FSlack%20-%20Plink.mp3
3|1|18|19|4|invaliduri
残件のチケットを作成したのでcloseします。
概要
期待値
対応内容
参考情報
備考
*