nsaito92 / Frock

0 stars 0 forks source link

ローカルの音楽ファイルを元に、色々な曲をアラームに選択できる様にする。 #9

Closed nsaito92 closed 4 years ago

nsaito92 commented 4 years ago

概要

期待値

対応内容

参考情報

備考

*

nsaito92 commented 4 years ago

対応開始。

nsaito92 commented 4 years ago

ざっくり必要と思う機能

対応する順番

アラームに使用する音楽ファイルをユーザーに選ばせる機能

まずは、上記でどこまで外部アプリに任せられるか調べる。 それ次第で実装する量が変わるため。 こちらの対応の様に自前の画面で、一覧を表示することもできるが、 出来れば、他アプリに任せたい。

nsaito92 commented 4 years ago

アラーム実行時、永続化しておいたファイル情報を元に、アラーム時に再生する機能

外部ストレージのファイルを読み出して、FileDescriptorを生成する方法

関連情報

nsaito92 commented 4 years ago
nsaito92 commented 4 years ago
URI取得パターンの例
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
adbで行う場合
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/*"
nsaito92 commented 4 years ago

試したこと

1 (NG)

    /**
     * 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)

2(NG)

こちらの記事を参考にした。


    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)

3

権限追加して、端末上で酒毒で権限追加。

    <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
nsaito92 commented 4 years ago

間が空いてしまったので現状整理

nsaito92 commented 4 years ago

ファイル選択機能

クラス修正

DB操作周り
ユーザー操作周り

エビデンス

新規作成したカラムにデータ追加、修正、削除が行えることを確認。

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 です。

nsaito92 commented 4 years ago

現状整理


* 次に永続化した情報を元に、アラームサービスにセットする処理を作り込む。(ド正常系)
* それが出来たら、非正常系、異常系処理を対応。
nsaito92 commented 4 years ago

考えてなかった点

nsaito92 commented 4 years ago

進捗

nsaito92 commented 4 years ago

進捗

nsaito92 commented 4 years ago

■対応したこと

■見えている課題

■別チケット

nsaito92 commented 4 years ago

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
nsaito92 commented 4 years ago

残件のチケットを作成したのでcloseします。