Friday, December 12, 2014

ベータ版2142000080をリリースしました。

2142000080をリリースしました。
リリース内容は以下のとおりです。

・Playlist画面、Ampache画面、キャッシュ一覧画面を実装しなしました。
具体的にActionBarをやめてToorlBarに対応し、Fragment化を行いました。
これにより、キャッシュ一覧、再生中、アルバムアートと3画面あったメイン画面のうち、キャッシュ一覧の画面を置き換えることができるようになりました。
ただ、この機能はまだ実装中なのでこれに対応しているのは、プレイリストとAmpacheのみです。今後、Dropbox,Box,GoogleDrive,LocalStoregeと対応していきます。
使い方は、サイドメニュー上のAmpacheやPlaylistの項目を長押しをすることメニューが表示されるので、そこから「ホームに設定」を選択すると置き換えることができます。
ホームに設定を選択
・カテゴリ、ソート、表示スタイルを変更できるようになりました。
これは機能によって異なりますが、キャッシュ一覧に関しては、グリッド表示、リスト表示を選択できるようになっています。

・AmpacheのVideo再生に対応しました。
AmpacheのカテゴリをVideoにするとAmpacheに登録されているVideoが一覧に表示されます。

・プログラムを最適化し軽量化しました。
いくつかの依存ライブラリを見直ししプログラムを最適化しました。

・いくつかのバグを修正
たくさん修正したとおもうけど、、、

・320x480の端末でイコライザが操作できない問題を修正しました。



Monday, December 8, 2014

開発状況

毎回、このブログを英語で書くべきか日本語で書くべきか悩むところなのですが、、
いまのところまだ日本人のほうがユーザが多いので、日本語でブログを書いています。
それに僕自身英語苦手なので細かいニュアンスを伝えることも難しいですし。


Monday, December 1, 2014

JustPlayerベータ版の登録

ベータ登録の流れ

1 ベータユーザの権利の取得
下記グループへ参加
https://plus.google.com/u/0/communities/106163650254898148553


2 ベータ版のダウンロード
下記URLからダウンロード
https://play.google.com/apps/testing/jp.co.kayo.android.localplayer

Friday, November 28, 2014

不具合、要望、現在のタスク等の確認はIssueサイトへ

不具合、要望、現在のタスク等の確認はIssueサイトへお願いします。

下記のURLはプロジェクトを管理しているサイトの一部になるIssueサイトです。
英語か日本語で書いてください。
https://bitbucket.org/yokmama/just-player3/issues?status=new&status=open


Tuesday, November 18, 2014

Ampache setting check point

1.Did you click Save in the upper right corner of the check button after checking the connection?


2. Whether authentication is successful of Ampache?
Successful it has become the Connected If you are.
connfig
3.Menu of Ampache has been added to NavigationDrawer?
Drawer will appear to slide from left.

Monday, November 17, 2014

新しいJust Playerをリリースしました

約1年近くかけてアプリを再実装し、新しくJust Playerを作り直しました。
このアプリは、Android2.1が発表された当時、時期的には私がXperiaX10を購入した際に、自分で音楽アプリを作ってみたいという気持ちからはじまったものです。
アプリを通じて私自身のAndroidへの理解を深めることを目的としていたため、音楽プレイヤーに本来必要でもないようなものも積極的に実装してみたりとあまりユーザのことを考えていないわがままなアプリだったと思います。
Just Playerの名前は「ただのプレイヤー」という意味を込めたつもりです。
つまり、最高のプレイヤーではなく、単純に音がなればいいでしょ、てきなものでした。
それでも、ユーザ数が増えてくるにつれ、ユーザがどのような機能を欲していて、どういいうアプリであれば使いやすいのかということを考えるようになってきました。

現在、ただ音がなるだけでなくJustPlayerの代名詞はクラウドデータを再生することが目的になっています。
これは本来の目的ではなかったのですが、そういうことになったならそうしましょう。ということで、新しく作成するJust Playerはクラウドのデータを再生することを主眼に置いて作りなおしました。

クラウドのデータは、サービスによってデータの持ち方が異なります。なのにユーザによっては複数のクラウドで使い分けをしている場合もあるとおもいます。
なので、どのクラウドでデータを管理していても、全部同じように使えることを目標にしました。
そして、新しいJust Playerではプレイリストには複数のサービスのことなるデータをまとめていれることができます。

それから、音楽データの管理方法はユーザによって様々です。
これは賛否両論があるとはおもいますが、アプリ側が決めつけたデータの管理方法も必要だとはおもいます。しかし、私の考えではユーザが自分で管理しているデータをそのままつかえることのほうが大切だとおもっています。

そのため、新しいJustPlayerは基本としてはフォルダ階層で管理されたデータをそのまま表示し、そこから再生できるようにしています。

しかし、この状態だと、検索もできないし、並び替えもできないです。
なので、アプリ側でも音楽へのアクセスを1画面だけ準備しています。
必要最低限ですので、他のアプリと比較して物足りないところもあるとおもいますが、一番使うであろう画面にしましたので理解はしやすいと思います。

次に再生についても見直しました。
シャッフル再生、リピート再生、ギャップレス再生、クロスフェード再生、タグ編集、歌詞表示と、当たり前のことが最低限できるようにしました。

それと、新しい機能として、ブックマーク機能をいれました。
これはまだ全てが完成していませんが、最小の機能だけ実装しています。
このブックマーク機能は音楽の一部の部分を一つの音楽として抜き出しプレイリストに追加することができる機能です。
考えられる使い方は、60分とか90分という長い曲の頭出しに使えますので、英語の勉強や、クラシックの頭出し等に便利だと思います。

だいたい、こんなかんじです。

古いJustPlayerでは出来ていたことが新しいJustPlayerでは出来なくなっている機能もあります。
これは、私個人の主観であまり必要ではないだろうという判断で削除されました。
もしその削除された機能のうちどれかが重要だったというのであれば、遠慮なく私にリクエストしてください。

JustPlayerは今後もユーザの意見をとりいれ、さらに変化させていくアプリでいたいと思います。







Friday, November 14, 2014

最終ベータをアップロードしました

リリース前の最終ベータをアップロードしました。
バージョンは2142000067です。

リリース前になりましたので、いくつかの機能が有料になっています。

有料になった機能
GoogleDrive、Dropbox、Boxへのアクセス
それから、アドバンス設定
これらはそれぞれ300円です。
また、一括で解除できるサービスパックとして1000円のものも準備しています。

それと、古いJUST PLAYERで既に寄付をしていただいているユーザに対しては、GoogleDrive,Dropbox,Boxを無料で使えるようにしています。

いくつか有料になりましたが、JustPlayerは基本機能だけで、音楽の再生から、クロスフェード、アルバムアートの検索、タグの編集といったことが広告なしで使えますので普通に利用する分にはお金を払う必要はないと思います。
あと、個人的にAmpacheが好きなのでこれは無料になっています。

2,3日状況をみて問題がなければこのままリリースになります。

あと今回のバージョンで新しく追加された機能として、
MP3に対して、タグ情報、アルバム情報を保存できるようにしました。
あと、いくつかUIを最適化しています。

Thursday, November 6, 2014

ベータ版バージョン2142000064をアップロードしました

毎回思うんだけど、今回のバージョンが一番良いのでしばらく修正はしなくてもいいだろう。
とおもうんだけど、毎回、前のバージョンは最悪、さっさと更新しないといけない。

とおもってしまうのはなんでですかね、、やっぱりテストが不十分なのが問題なのか、、なのか。

さて、今回のバージョンから一部のユーザにとって待望の歌詞表示機能が追加されました。
歌詞は、MP3に限られますがMP3のヘッダ情報にかかれている歌詞データを読み取って表示しています。
しかし、歌詞にはいくつかフォーマットがあるのですが、それら全てに対応しているわけではありません。
2つ程対応しました、多分メジャーだとおもう。もしこのフォーマットが読めないのでなんとかしてほしいという要望があれば、私までご連絡ください。
その際には、どの環境のどのツールで作成しましたということも合わせてご連絡頂きたいです。

それと歌詞の編集機能ですが、JustPlayer上では編集ができるようになっています。
だけど編集された歌詞情報はMP3には保存していません。
これはタグ情報や、アルバムアートも同じですが、オリジナルのファイルを書き換えることをしても良いのか?またそうして壊れた場合どうすればいいのか?そういうことを考えると余計なことをしたくないというのが本音です。

だけど、それだと不便という人もいるとおもうので、有料になるとおもうのだけど、あとで追加する予定です。



Tuesday, November 4, 2014

歌詞表示を実装してみた

MP3から歌詞を取得できるようになったので、早速実装してみた。
実装するにあたり、どこで歌詞の表示を切り替えるか、検討してみた結果画面下部にドロワーを設定し、そこで表示の切り替えを行うことにした。
歌詞を表示している画面(時間表示のバランスが悪いので要検討)

画面下部から引き出したメニューにより歌詞の表示を切り替える
ドロワーにはスペースがあるので、ついでに、イコライザやクロスフェードといった機能の有効、無効ができるボタンも追加した。

とりあえず表示ができただけなので、次はタグ編集画面で歌詞を設定できるようにするようにし、そこまでできたらストアにアップロードする予定です。
しばらく様子をみたいので、正式リリースはもうちょい先です。



Monday, November 3, 2014

ベータ版2142000061をアップロードしました

しばらく、Google+のほうだけに情報を公開していたたため、ここだけをみている人にとっては、ずいぶん更新をしていないかと思われたかもしれません。
ちゃんと開発をしています。
ビルドバージョンはずいぶん進んで61になりました。
ちなみに、このビルドバージョンの意味は
2142000061の2はこちらの管理番号つづく、14は最小のSDKのバージョン番号、そして20はターゲットにしているSDKのバージョン番号、そっから0が続いて、61がビルドにつけているナンバリングです。
だいたい、PlayStoreにアップする度にカウントアップしているので61回アップデートしたことになりますね。。長い



Friday, October 17, 2014

CrossFadeができる端末とできない端末がある

ユーザの要望でクロスフェード機能を実装してみたのですが、この機能のためいくつか犠牲になっているものがあります。
そのまえにクロスフェードとはどういう機能なのかというと、曲の終わりをフェードアウトし、次の曲のはじまりをフェードインすることを同時に行う機能です。
JUST PLAYERはクロスフェードの設定を有効にすると、曲の終了6秒前にフェードアウト処理にはいり、同時に次の曲をフェードインします。
いまのところ6秒固定になっています。
この数値を変更出来るようすることは可能ですが、いまのところ変更するUIを実装していません。マニアックな機能なので特に必要だとはおもっていませんが、もし要望があれば検討したいです。

実際の実装方法は、2つのMediaPlayerを準備し、片方の時間をチェックし、6秒前にはいったら、次の曲を再生するという単純な方法なのですが、これをつかうことで、一時的ではあってもMediaPlayerのインスタンスを2つ準備しなければなりません。
これは、ギャップレス再生でも必要な処理なのでこれ自体は問題ではないのですが、ギャップレス再生とは異なり、違うボリュームをそれぞれに適用する必要があるためAudioSessionIDを共通化することができなくなります。
つまり、AudioEffectも別々になるというわけです。
この問題は、これまで何度MediaPlayerを作りなおしてもAudioSessionIDを共通化しておけば、AudioEffectは共通でつかえていたものが使えなくなったことになります。
そのおかげで、Equqlizerの処理、Visualizerの処理といったAudioSessionIDをもとにインスタンスを生成していた処理の扱いが面倒になってしまいました。
いろいろ、苦労はあったものの今のところなんとか、うまく動いている状態までもってこれました。(手元の最新版において)

しかし、完璧というわけではなく一部の端末では、MP3ファイルを同時に再生するとStartが実行されない問題がおきています。
具体的にいうと、Nexus5さん。

これは個体差があるのかもしれませんが、2台の端末で同じ現象を確認しています。
簡単なサンプルプログラムを作ってもやはり同じ現象がおきるので、MediaPlayer自体に問題があるのではないかと思っています。






Friday, October 10, 2014

beta update version 2142000047

リリースまでもうすぐ、、のはず。
長いよー長いよー早くリリースしてゆっくりしたい。
こちらのIssueが全部解決されたらリリースする予定です。
https://bitbucket.org/yokmama/just-player3/issues?status=new&status=open

あと、1,2週間ぐらい。

今回のバージョンは色々修正しています。
UIでは、選択方式を全面的に見直しました。
Visualizerに関しては処理を高速化し省電力化しました。
Equalizerに関しては画像を綺麗にしました。
Playに関しては、おかしな動きがある不具合などを修正しました。
アプリ内課金は、とりあえず実装しました。今のところ課金しなくても全機能が使えます。

こちらの端末では安定して動くようになっています。
UIをきちんと作ったイコライザ、結構苦労しました。


Wednesday, October 8, 2014

Ampache SelectView renewal

Ampacheの選択画面を再実装しました。

Ampacheにかぎらずファイル選択画面は全部変更しました。
基本的にCheckboxの廃止です。
タップで曲選択、再生が基本となり、ロングプレスから複数選択、置き換え等ができます。

Tuesday, October 7, 2014

GC_EXPLICITが出ないように対策

JUST PLAYERのログをずっとみていると、次のようなログが頻繁にでていました。
 
GC_EXPLICIT freed 5773K, 34% free 27728K/41588K, paused 17ms+20ms, total 267ms
GC_EXPLICIT freed 41K, 75% free 2829K/11252K, paused 2ms+2ms, total 27ms

発生するタイミングを調べるとどうやら、ContentProviderでQueryをするタイミングだということがわかりました。


該当するクエリ処理をみてみると、どうやらsetNotificationUriが怪しい

cursor.setNotificationUri(getContext().getContentResolver(), uri);

試しに上記のコードの部分をコメントアウトすると、GC_EXPLICITがでなくなりました。
setNotificationUriは、registerContentObserverで登録されたコールバックに通知が届くようにするための設定処理なのでコメントアウトするわけにはいきません。 しかし、必要のないQueryに対しても常に設定するのは勿体ないです。 なので、ここは、必要なクエリとそうでないクエリを判別できるようにし、必要なクエリだけ設定するように変更しました。下記は自作のContentProviderのQuery処理です。

        boolean needSetNotify = false;
        if(uri.getQueryParameter("notify") != null){
            needSetNotify = true;
        }

        //クエリ処理

           Cursor cursor = queryBuilder.query(
                getSQLiteOpenHelper().getReadableDatabase(), projection, selection,
                selectionArgs, groupBy, having, sortOrder);
        
        if(needSetNotify) {
            cursor.setNotificationUri(getContext().getContentResolver(), uri);
        }


こんな感じで、自作のContentProviderに仕込んでおく。
そして、ContentObserver.onChangedのイベントが必要なクエリ結果の場合だけ、下記のようなクエリのためのUriを発行する。
 
        Uri uri = PlayOrderContentProvider.PLAYORDER_CONTENT_URI
                .buildUpon()
                .appendQueryParameter("notify", Boolean.toString(true))
                .build();

これをいれておくことで、通知が届くCursorを取得することができます。
GC_EXPLICITを回避しパフォーマンスが向上しました。
次のバージョンでFIXされます。


Wednesday, October 1, 2014

イコライザを引っ込めました

画面の仕様を変更しました。
いままでは、

・プレイリスト
・アルバムアート
・イコライザ

となっていましたが、イコライザを設定と同じ場所に移動し、かわりに

・プレイリスト
・アルバムアート
・メディアリスト

に変更しました。

メディアリストには、すでに再生したことがある、あるいはメディアスキャンによって登録された曲から、アルバム表示、アーティスト表示を選択することができます。
右上のアイコンで表示を変更できます。


Indexを設定しアーティスト順で分かりやすくしています。


Saturday, September 27, 2014

タグの編集画面を追加

簡易的だけどタグの編集画面を追加しました。
タイトル、アルバム、アーティスト、それからアルバムアートの変更ができます。
それ以外については、要望があれば今後追加していくけど、画面に表示されないデータを更新する意味があるのかという気もする。

あと、アルバムアートは、AppEngineを使って画像を収集しているので、あんまりアクセスが多いとやばいかもしれない。
ベータで様子をみて、クライアント側で処理するかどうか検討する予定。

あと、リピートができない不具合を修正しときました。

Friday, September 26, 2014

CrossFadeを実装しました

今回の修正で一番大きいのはCrossFadeです。
設定画面からCrossFade再生をOnにすることができます。

そのほか、AudioVisualizerの計算でFFT処理でまずいところがあったので、修正しました。
イコライザを動かすとちゃんとそれに連動してVisualizerが変わるようになったので、やってみてください。
それと、再生画面の再生中のアニメーションもVisualizerと連動するようになっています。

そのほか、いくつかバグ修正をしました。
再生部分の処理は、大幅なリファクタリングをしたので、Boxでうまく動かなかった人も一度試してみてほしいです。治っているといいのですが、、

Wednesday, September 24, 2014

issues site opend.

issues site opend.
Requests and bug reports JUST PLAYER (Beta) of from here

不具合・要望の報告サイトを準備しました。
サイトは下記のURLから

https://bitbucket.org/yokmama/just-player3/issues?status=new&status=open


Monday, September 22, 2014

I był wspierany w polskim

I dodaje język polski.


To jest ekran menu.
Przetłumaczyłem wszystko także opis ekranu ustawień.

Friday, September 19, 2014

indexファイルのすすめ

Just Player独自のプレイリストフォーマットである、Indexファイルを使うと次のようなことができます。

60分とか90分とか長時間の音源データをクラウドサーバーに置いた状態で、それを全てダウンロードせずに、目的の位置の音を鳴らすことができます。

具体的には、このリンクの動画

https://www.youtube.com/watch?v=cLijO1UAIiQ

これは、複数の音楽を連続再生する動画です。
これに目次をつけると次のようになります。

1 現実的論理主義者
2 夜咄ディセイブ
3 ロスタイムメモリー
4 想像フォレスト
5 如月アテンション
6 チルドレンレコード
7 六兆年と一夜物語
8 ヘイセイカタクリズム
9 キミのことが好きでゴメンナサイ
10 イアイア★ナイトオブデサイア
11 四季刻歌
12 宵、桜
13 イアイア☆イヤークラッシャー 

これを、Indexファイルにすると次のような内容になります。

ARTIST "IA"
TITLE "ボーカロイド IA 好きが選んだ個人的メドレー"
FILE "ボーカロイド IA 好きが選んだ個人的メドレー.mp3"
TRACK 01
TITLE "現実的論理主義者"
ARTIST "IA"
INDEX 00:00
TRACK 02
TITLE "夜咄ディセイブ"
ARTIST "IA"
INDEX 04:33
TRACK 03
TITLE "ロスタイムメモリー"
ARTIST "IA"
INDEX 07:50
TRACK 04
TITLE "想像フォレスト"
ARTIST "IA"
INDEX 12:35
TRACK 05
TITLE "如月アテンション"
ARTIST "IA"
INDEX 16:47
TRACK 06
TITLE "チルドレンレコード"
ARTIST "IA"
INDEX 20:52
TRACK 07
TITLE "六兆年と一夜物語"
ARTIST "IA"
INDEX 23:52
TRACK 08
TITLE "ヘイセイカタクリズム"
ARTIST "IA"
INDEX 27:28
TRACK 09
TITLE "キミのことが好きでゴメンナサイ"
ARTIST "IA"
INDEX 30:40
TRACK 10
TITLE "イアイア★ナイトオブデサイア"
ARTIST "IA"
INDEX 34:18
TRACK 11
TITLE "四季刻歌"
ARTIST "IA"
INDEX 38:36
TRACK 12
TITLE "宵、桜"
ARTIST "IA"
INDEX 42:30
TRACK 13
TITLE "イアイア☆イヤークラッシャー"
ARTIST "IA"
INDEX 46:16

冒頭には、このファイルの説明をいれます。
ARTISTは歌をうたっている人、グループ
ALBUMはこの楽曲のアルバム名(上記のサンプルではありませんが)
FILEはこの楽曲のデフォルトのファイル名

TRACKの項目は、目次を意味しています。
TITLEが目次の名称
ARTISTは目次の部分のアーティスト名
ALBUMは目次の部分のアルバム名、省略すると、冒頭で定義されたものが適用されます。

このファイルを拡張子を .indexにして、音源ファイルと同じフォルダにおいておくと、
JustPlayerからIndexファイルを選択することで、自動的に目次を読込み、プレイリストに追加します。

※ちなみに、上記URLの動画の音源データの入手方法は知りませんので、あくまで参考例として考えてください。

現在、音源に目次を設定し、保存する機能を実装中です。
ですので、いまはこのファイルは手動で作成しないといけないですが、すごく便利なのでぜひお試しください。

あと、この機能ですが、
GoogleDriveではうまくうごきません。
動作を確認できているのはDropbox、Box、Ampache、内部ストレージです。




Thursday, September 18, 2014

Logcatのログの送信機能を追加しました

Logcatのログは以前は端末のログを全部取得することができていたのですが、最近では自アプリのログしか収集できなくなっています。
そのため、別アプリによってログを収集しバグ報告をするという事が出来ないです。

今回のアップデートで、設定画面からアプリのログをメールに添付する機能を追加しました。
これを実行すると、Logcatのログを添付ファイルにし、Gmailクライアントに連携することができます。
メールボタンを押したあとすぐにメールが送信されるわけではないので、内容が気になる場合はメールの添付ファイルを確認してから送っていただければと思います。
とはいっても、あくまで動作がおかしいという場合に修正をご依頼する場合のみ送ってください。ログを送っていただければ、それをもとに問題の原因を把握することができるかもしれません。

Logcat確認画面
それから、今回のリリースで変更されたものとして次のようなものがあります。

・プレイリストから再生中リストへの追加でアルバム、アーティスト名等が反映されない不具合を修正
・再生にあわせて再生中リストの表示位置を移動するよう修正
・再生中リストをクリアしたあと、アンドゥができるように修正
・画面下部のコントロール部分でジェスチャーによって、次の曲へ、前の曲へ、停止、再生ができるように修正
・通知エリアのコントロールの☓ボタンはアプリの終了をするように変更
・いくつかのアイコン、画像、レイアウトを修正

ストリーミング処理も少し修正をしていますので、動きが変わって前よりおかしくなっている可能性もあります。なにか問題がある方はご連絡いただけると助かります。


Monday, September 15, 2014

アルバムアートの取得と、バッファリング状態の表示を追加

キャッシュデータの状態を表示するようにしました。
といってもアイコンがまだなので、いまのところ文字です。
SD:ストレージデータ
CD:クラウドデータ
1−100:作成状態のパーセンテージ

それと、アルバムアートのクイック検索機能を追加しました。
右上の検索ボタンをおすと、タイトル名、アーティスト名から該当するカバーアートを設定します。


あともうひとつ、けっこう以前から実装していたのですが、報告し忘れていました。
設定画面から、例外のレポートを送ることができます。
アプリが落ちたあとに、やると落ちたときの例外メッセージを添付できるので、なにか問題があったときはこれを使っていただけると助かります。

Sunday, September 14, 2014

ストリーミング再生と、次の曲のキャッシュ作成のパスを分けてみた

いろいろ工夫してみたけど、ストリーミング再生用のデータ取得処理と、次の曲のキャッシュ作成を同じような作りでやっているのは無理がでてきたので、大きな修正になるけど別々の処理として行うように変更してみました。

Boxにかぎらず、ほとんどのクラウドサービースはダウンロードをしないでずっと止まっていると、ネットワークが切断されたと勘違いして接続を切断してきます。
ストリーミング処理の場合、とくに音楽再生の場合再生するバッファだけクライアントが取得したら次の取得は、必要になるまで開始されません。
Androidの端末によっては、このバッファの取得サイズが違うようで、たくさんとるものや少ないものもあるように思います。(ここは憶測です)
問題はこの大きいバッファの場合で、この場合長い間通信が止まった状態になっているのだとおもいます。

今回特に問題になっているのは、次の曲の再生処理です。
今までは、曲の切り替わりを素早くするために、次の曲を事前に読み込んでおく処理をいれていました。
しかし、これをMediaPlayerにまかせていたため、再生されない状態でずっとほっとかれるため、バッファの読込処理もずっと止まった状態になります。
これが、次の曲の読込で失敗する原因です。

一つ前の修正でひとまずMediaPlayerにまかせっきりで処理をしていた部分を自分で行うように変更してみました。
これで、ある程度解決できたのかなとおもっていたのですが、まだ失敗する場合があるようなので、さらに原因を調べてみていたのですが、、ここまでずっと修正修正ときていたので、問題の箇所のコードが難しくなりすぎ、理解しずらくなっていました。
なので、ここは思い切ってリファクタリングをすることにし、処理を別々に分けることにしました。

ということで、今回の修正はプログラムを最適化したリリースになります。
ダウンロード専用のコードを書いたので、前より早くなっていると思います。

今回の修正でダウンロードの事前処理を容易に行えるようになったので、長らくほったらかしになっていた、「デバイスに保存」機能の実装にとりかかろうかと思います。ついでにダウンロード中か、どうかのステータス表示もいれます。(だけどアイコンで悩み中、、)


Friday, September 12, 2014

Boxのファイルを連続再生していて途中で止まる現象に悩む

Boxの再生について前回の修正でだいぶましになったと思っていたのですが、やっぱり途中で止まる不具合が発生しています。
しかもとまるだけじゃなく、延々とリトライをする始末。

どうして、このような事がおきるのかというと、Boxにファイルをダウンロードリクエストすると、途中で失敗するケースがあるので、続きは途中からのリクエストを作成するようにする必要があります。(ここは前回の修正の範囲)
だけど、これだけでもまだ問題があるようで、途中からのリクエストをした場合には途中からのリクエストを返しました、とBoxから返事がくるはずなのですが、なにを勘違いしたのか、特定のファイルでは最初からダウンロードを要求したのと同じ結果をかえしてくる場合があります。
そのため、こちらは混乱してしまいます。
最初からのデータを返してくるというのなら、それなりに正常系の処理として対処の使用があるものの、ヘッダ情報だけはいっていて中身がありません。
それで、データのチェックの際、上記でおかしな点がみつかりエラー処理をするのですが、今度はMediaPlayerがそれに納得いかないのか、もう一回、もう一回と再リクエストをしてしまい、ずっと読み込み中の画像がでてくる状態になっています。

この問題について、手元のバージョンでは強制的にMediaPlayer側に停止をするようにプログラムで回避する修正をしました。
といってもMediaPlayerが諦めてくれるまでに30秒ぐらいはかかる感じです。




Thursday, September 11, 2014

イコライザを修正しました

イコライザで未実装だった箇所を実装し、UIを見直しました。
画像はひとまず適当なものを当てているので見た目は地味なかんじです。
正式リリースまでには良いものに変更したいと思っています。


Wednesday, September 10, 2014

あー、いろいろバグいれこんでしまってるみたい

とりあえず既知のバグとして

・SDカード内の音楽の再生で次の曲にいくときに停止してします。
・キャッシュが作成された音楽なのに先読みが実施されてなくReplayGapが効果してない。

あと他にもあったら追記しておきます。
次のリリースで修正されます。内容が内容だけに次のリリースは早めになるとおもいます。

Tuesday, September 9, 2014

ブックマーク機能をひとまず実装してみました。

えーと、ブックマークというのは任意の音楽のある一部分をブックマークし、曲のように扱う機能のことです。

ブックマークというのが妥当な名前なのかどうかは分かりませんが、他にこのような機能を持っているアプリがないので、分かりやすい言葉がしっくりくるだろうとこの言葉にしました。


クライアントのバッファリング処理の実装を見直してます。

BoxのAPIを更新してから頻繁にコネクションが切れる現象に悩まされています。
切れるだけならまだしも、何度か失敗するとAudioManagerがハングアップして音が一切ならなくなる不具合に見舞われてるのでかなり問題。

原因はなんなのかなぁーといろいろコードを見なおしてみてるけど、よくわからなかったのですが、もしかしたら、という仮説を考えています。
その仮説というのは、MediaPlayerのバッファリングがいつまでたってもReadしてくれないのでサーバーがコネクションロストと判断して切断してるんじゃないのかなということです。
理由は、だいたい決まって30秒程度で失敗しているのとStackTraceのエラー内容から、、
MediaPlayerは再生分よりも多めにバッファリングしてますが、ある程度再生しないと次のバッファを読み込もうとしません。だからかなぁ、、
対応策として、ダウンロードのラインとMediaPlayerに供給するラインを別々にすることだとおもうので、ちょっと試しにこの実装をいれようかなとおもってます。
というわけで、次のバグ修正版のリリースが遅れると思います。
明日作業を見積もって長くかかりそうだったら、一旦現時点でバグを潰したバージョンをリリースします。

Friday, August 29, 2014

ヒストリ機能改め、プレイリスト機能を実装しました

実際に使ってみてヒストリ機能が微妙だったのでどうしたものかと悩んだ挙句、プレイリスト機能として保存されたプレイリストと自動保存される履歴をまとめてプレイリスト機能として実装しなおしました。

若干スクショ多め


Thursday, August 28, 2014

java.lang.UnsupportedOperationException: Effect library not loaded について

多分旧JUST PLAYERから引き継いでいた不具合だとおもうのですが、今日は少し進展がありました。

具体的には下記のようなエラー

java.lang.RuntimeException: Unable to create service jp.co.kayo.android.localplayer.service.MediaPlayerService: java.lang.UnsupportedOperationException: Effect library not loaded
at android.app.ActivityThread.handleCreateService(ActivityThread.java:2314)
at android.app.ActivityThread.access$1700(ActivityThread.java:129)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1228)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4475)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:559)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.UnsupportedOperationException: Effect library not loaded
at android.media.audiofx.AudioEffect.(AudioEffect.java:384)
at android.media.audiofx.Equalizer.(Equalizer.java:146)
at jp.co.kayo.android.localplayer.media.AudioEffect.attach(AudioEffect.java:120)
at jp.co.kayo.android.localplayer.media.MediaController$GaplessMediaPlayer.setTrack(MediaController.java:758)
at jp.co.kayo.android.localplayer.media.MediaController.init(MediaController.java:90)
at jp.co.kayo.android.localplayer.service.MediaPlayerService.onCreate(MediaPlayerService.java:57)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:2304)
... 10 more

これは一つ前のポストでも取り扱っていた不具合ですが、単純にエラーの原因をみると、Equalizerの生成ができなくてエラーになっています。
エラーの内容が「 Effect library not loaded」なのでサポートされていない端末だからエラーになったのかな?と思ってしまうのですが、現象をみると動く場合もあるのでそういう問題ではないです。
なので、他の原因によって生成が失敗してしまったということだとおもいます。
この例外をGoogleで検索したところいくつかヒットするのですが、その中でも興味深いの次のリンクです。

http://stackoverflow.com/questions/10536170/equalizer-not-always-supported-even-when-api-9

返答は、Eqauzlierのreleaseをしていないから

多分そうだとおもいます。

だけど、EqualizerのReleaseのタイミングはけっこう難しいです。なぜなら音楽プレイヤーのほとんどはServiceで制御するように実装します。
つまりMediaPlayerのインスタンスはServiceが保持するので、必然的にそれに紐づくEqualizer等のAudioEffectはServiceが保持することになります。
しかし、Serviceの場合、onDestroyが呼ばれないケースが存在します。
だから、EqualizerのReleaseのタイミングを逃すケースが存在するのです。
おそらく、上記の不具合はそのようなケースにおいて発生するのでしょう。

多くの端末では、1度や2度Release漏れがあっても問題なく再生できるし、またほっとけば自動的にReleaseされて正常になりますが、そうでない端末もあるようです。
現に私が常時利用しているNexusではそのようなことが発生したことがないです。

今日、たまたまArrowsの端末を使ってテストをしていたら偶然上記の不具合が発生しました。
そして、その理由を考察するにあたり、「APKのインストールを繰り返す」
からではないかと考えています。
理由は、APKのインストールをすると、Serviceは強制的に終了させられるので、onDestoryが呼ばれません。

だいたい原因がわかったので対策をすることにしました。
ひとまず、2つの対策をしてみます。

1 Serviceが強制終了しreleaseが行われなかったとしてもEqualizerのインスタンスは再利用されるように、staticにして保持しておく。

2 とにかく、生成に失敗してもアプリが終了しないようにtry-cacheをしておく。
もちろん、nullになるので次回リクエストのタイミングで再度生成を行う。


                try {
                    Equalizer equalizer = new Equalizer(mPriority, audioSessionId);
                    if (supportFx(descriptor, equalizer.getDescriptor())) {
                        sEqualizer = equalizer;
                    } else {
                        equalizer.release();
                    }
                }catch (Exception e){
                    Log.e(TAG, "EqualizerのReleaseがうまくいってなくてこれ以上生成できないって言われてる。", e);
                }

これで様子を見てみようとおもいます。
手元の端末では一応動作しているのですが、、

ちなみにリリースですが今日中は無理かな、、、
プレイリストの実装がもう少しかかりそうです。

Wednesday, August 27, 2014

自動でボタンを押した感をだすボタンの作成

Android-Lだとボタンに画像を貼ってそのままでボタンをおしたときのセレクターが自動で実装されてる感じなので、これいいなとおもっていたのですが、しばらくAndroid-LのSDKが下位レベルでサポートされない可能性を考えると自前で実装したほうがよさそうです。

基本的にAndroidのボタンは、なにもしていない状態、押した時の状態と画像を別々に準備し、それをselectorという画像切替用のXMLファイルを別途定義する必要があります。
これが地味に面倒くさい。
Photoshopであらかじめ彩度をおとしたりした画像を準備していました。

IOSだとこの辺りが自動だから楽なのでAndorid面倒くさいなぁとおもわれる点でもあるのですが、ちょっとこれも工夫をすると少しは楽になります。

public class AutoEffectImageButton extends ImageButton implements View.OnTouchListener{
    private ColorFilter mFilter;
    public AutoEffectImageButton(Context context) {
        super(context);
        setup();
    }

    public AutoEffectImageButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        setup();
    }

    public AutoEffectImageButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setup();
    }

    private void setup(){
        mFilter = new PorterDuffColorFilter(0x64FFFFFF, PorterDuff.Mode.DARKEN);
        setOnTouchListener(this);
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                getDrawable().setColorFilter(mFilter);
                v.invalidate();
                break;
            }
            case MotionEvent.ACTION_UP: {
                getDrawable().clearColorFilter();
                v.invalidate();
                break;
            }
        }
        return false;
    }
}

上記のクラスのように押したときに、ボタンの色を変更する処理を実装するとプログラムでボタンをおしたときに彩度を落としてボタンを押した感じに表現することができます。
フィルターにはいろいろあるのでアプリに合うエフェクトを使うといいでしょう。
ちなみに、下記のサイトにPorterの違いを一覧にしてくれているサイトがあったので重宝しました。

http://d.hatena.ne.jp/gae+eyo/20111123/1322026548


Tuesday, August 26, 2014

ファイル選択ダイアログでフォルダを複数選択できるようにしました

「フォルダを選択したら、そのサブフォルダも検索してほしい」
という要望があるのだけど、これは非常に難しく、実装はたやすいけど、そのあとのフォローが難しいとおもっています。
なぜなら、SDカードならフォルダ内の一覧を取得するのは一瞬だけど、クラウド上のフォルダはその取得に10数秒かかる場合があります、それを再帰的に取得するとファイルの取得にすごく時間がかかってしまう。

プログレスバーは表示しないといけないし、途中で停止も実装しないといけないし、失敗した場合の例外処理もしないといけないしで手間だけ増えてくる。

これは、旧JUST PLAYERの仕様であり、悩みのたねでした。
旧JUST PLAYERではこれを何度もしないように一番最初に痛みをお願いするという形でフォルダのスキャンを行いインデックスを作ることで逃げましたが、この手法では、フォルダ状態が変わったときに再スキャンをしないといけないという欠点がありました。
クラウドサービスによってはフォルダの変更日付を取得できるものもあるのでそのようなサービスだけは起動時にチェックをすることも可能なのですが、取得できないものもあります。
なので、統一的なインターフェースを実装する場合、最小のサービスに合わせるしかないのが悩ましい点です。

新JUST PLAYERでは、これはもう面倒だってんでもう毎回フォルダを選択してファイルをいれてくださいという仕様にしたのですが、やっぱりいちいち選択するのが面倒臭いんですよね。

というわけで冒頭の要望がでているのです。

今回のバージョンでは、そのサブフォルダを自動で追加する機能はひとまずペンディングにし、複数のフォルダをまとめて選択し、追加できるようにしました。

これなら、アーティストのフォルダにあるアルバムを全選択するという手順だけど、いっぺんに曲を追加できることになります。
これでも不便なのかどうか、ちょっと様子を見たいとおもっています。

あと、今日アップロードしたバージョンで、AQUOSPADで落ちる不具合が治っているといいな。
いちおうそれっぽいところを修正してみたのだけど。
手元で再現をしないので、よくわからないです。

GooglePlaySeviceのDevelopderConsoleに下記のエラー報告がありました。
これは、AquosPadのエラーだったので多分これだとおもう。

java.lang.RuntimeException: Unable to create service jp.co.kayo.android.localplayer.service.MediaPlayerService: java.lang.UnsupportedOperationException: Effect library not loaded
at android.app.ActivityThread.handleCreateService(ActivityThread.java:2627)
at android.app.ActivityThread.access$1700(ActivityThread.java:150)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1351)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5159)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:810)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:577)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.UnsupportedOperationException: Effect library not loaded
at android.media.audiofx.AudioEffect.(AudioEffect.java:384)
at android.media.audiofx.Equalizer.(Equalizer.java:146)
at jp.co.kayo.android.localplayer.media.AudioEffect.attach(AudioEffect.java:120)
at jp.co.kayo.android.localplayer.media.MediaController$GaplessMediaPlayer.setTrack(MediaController.java:736)
at jp.co.kayo.android.localplayer.media.MediaController.init(MediaController.java:90)
at jp.co.kayo.android.localplayer.service.MediaPlayerService.onCreate(MediaPlayerService.java:57)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:2617)
... 10 more

このエラーの原因自体はサポートされていないAudioEffectを使ったからおちていますがエラーの内容と、原因がずれているとおもいます。
プログラムのバグではスタックトレースと、エラーの原因が直結していないことはよくあることです。
多分ですが、EqualizerのAudioEffectのReleaseが正常にされていないのに、生成がされたためだと思われますので、終了処理の箇所を見なおしてみました。
これで治ってもらえると助かるんですが。。。



Monday, August 25, 2014

履歴(簡易プレイリスト)を追加しました

History(履歴)機能を追加しました。

この機能は、SDカード内の音楽や、クラウド上の音楽を選択し追加した際に、そのときに追加した状態をプレイリストとして履歴に保存する機能です。

履歴にはタイトルと説明、それと作成日付と更新日付が登録されています。
タイトルは、追加したときのフォルダ名が設定されます。
説明には追加した曲のタイトルを、区切りで64文字まで設定しています。
ただし、表示領域の関係でスマホだと25文字程度しか表示されていません。

Historyには上記の名前で表示されるのでそれを選択すれば、クラウドに接続しなくてもすぐに曲を入れ替えができます。
オフラインキャッシュが作成されているならこちらのほうが素早いとおもいます。

ずっと消えないように保存するのであれば、別途プレイリストをファイルに保存しておくことをお薦めします。

あと、Historyから再生すると更新日時が新しくなるので履歴としては上にあがってきます。
まだ未実装ですが、リリース迄には100件(この数字は要望があれば変更しますがひとまず100件で)以上の履歴は自動で削除するような仕組みになるので、よく聴くリスト的な位置づけになるとおもっています。

あと、まだHistoryの名前の変更などは実装していません。
履歴だけに変更するものなのかも悩みどころ。

既知のバグとして、
・MediaStoreの履歴名が日付になっています。
・アルバムアート表示画面が再生停止の状態だと画像が小さいままでみっともないです。
・イコライザの保存とかがうまく動いてないです。

LMP(通称:LemonMerengePie)が噂になっています。
JUST PLAYER2はMaterialDesign対応が主目的なのでLMPがリリースされ、SDKが正式になった際にリリースする予定です。
おそらく、10月頃だとおもっているのですが、もし遅れる場合はリリース日は再検討します。
それまではベータをご利用ください。




Tuesday, August 19, 2014

プレイリストを保存できるようにしました

プレイリストを保存できるようにしました。
だけど、まだ不十分です。

ひとまずできるようになったというところかな。

現在再生中(PlayQueue)に入っている曲の一覧を右上のEditボタンから編集できるようになりました。
編集は、ドラッグで曲の移動、削除ボタンで削除できます。
編集後、Menuからto playlist queueで、現在生成中のリストに反映します。

また、Saveでも生成中のリストに反映します。
それから、New Saveで新しいファイルにリストを保存できます。
この際ファイル選択ダイアログが表示されますので、任意のフォルダ、またはそのままファイル名をつけると保存されます。

この初期のフォルダですが、現在アプリケーションのフォルダになっているので、ちょっとわかりにくいと思います。
デフォルトのフォルダは設定で変更できるので、必要であれば変更してください。

しかし、ここまで書いていたこれは面倒くさい。。

実際のところ何も考えなくても簡単に保存、読込が利用できるように設計中です。

これからの実装
・自動プレイリスト保存
 これは、曲を選択し再生中のリストに追加すると自動でそのリストを日付で保存する機能です。これは、ある意味履歴のようなものなので、自動で生成されて、数が多くなったら古いものから消されていきます。このリストはDBに保存されるので、他のプレイリストとは異なります。


・任意のプレイリストファイルを選択し編集
現在再生中のリストだけでなく、ファイルで保存されたプレイリストを開いて編集できるようにします。

・所定の場所のプレイリストのフォルダを開く
NavigationMenuに保存されたプレイリストを開くためのショートカットを追加します。


あと、Boxnetの最大取得ファイル数を1000件にしました。



Wednesday, August 13, 2014

ネットで噂になってたスピーカー作ったけど期待した程音はよくなかった

夏休みはだらだらと過ごすものである。
結局僕は外に一歩もでないでコーディングをしながら音楽をきいて時を過ごしてしまいました。

Bebop最高!

不具合を少し修正し、リスト画面のレイアウトをいじりました。

・Backボタンを押すと、一曲目に移動する不具合を修正
・再生中のマークのアニメーションが再生に連動していない不具合を修正
・リピート設定にしていないのにリピートしてします不具合を修正

・リストビューのレイアウトを変更
・コントロール部のレイアウトを変更
・ポップアップメニューを追加(削除しか実装してません)
・クリアボタンを機能するようにした

あと、のんびりだけど、プレイリストの編集機能の実装にとりかかろうと思っています。
今日はそのレイアウトの検討で時間くっちゃいました。


それから、タイトルにもあるけど紙コップを作ったスピーカを作ってみた。
音が大きくなったなぁ(小並感)


Tuesday, August 12, 2014

夏休みに入りました

夏休みにはいったからといって、普段やっていることと大して変わらないのですが。。。
ちょっとだけ更新が速くなるかもしれないです。

今日はそれほど大きい進捗はないですが、次の不具合を修正しました。

・Notificationの終了時間が設定どおりに終了しない
 原因:設定した時間のミリ秒への変換処理が間違っていた。

・Backで前の曲にいこうとすると一曲目に移動した
 原因:前の曲の取得で並び順が昇順だったので一曲目が選択されていた。

それから、アルバムビューの表示をフェードイン、フェードアウトで画像を切替えるようにし、画像の移動をランダムにしました。

それから、APKの公開ですがダウンロードできるようにしてもインストールが容易ではないようなので、アップロードはやめることにしベータ版による公開にのみにしました。

ベータプログラムへの追加はJUST PLAYERのGoogleGroupかGoogle+へ加入が必要です。

Google+コミュニティー

GoogleGroupMailingList

登録すると下記のURLからダウンロードすることができます。
https://play.google.com/apps/testing/jp.co.kayo.android.localplayer

Sunday, August 10, 2014

Dropboxを再生してたら5秒ぐらいして、勝手に次にいくバグの原因はこれじゃないかな?

以前、JUST PLAYERのユーザからDropboxを使って再生をしているとき、いろいろ操作をすると5秒ぐらいしたら勝手に次の曲にくようになって一旦そうなると全部そうなるという報告がありました。
この現象は僕のところでは再現していなかったので、なんなんだろうとおもっていたのですが、Boxnetで長時間再生テストをしていたら、たまに上記のような現象が発生していたので調べて修正をしてみました。

台風につき作業が捗っております

台風が珍しく自宅周辺に上陸してきているため、家に閉じこもるしかありません。
外はとんでもない風でプランターがガタガタいっています。危ないのでびしょ濡れになりながら紐で結ぶとかしてました。

写真じゃわからないかもだけど、外の雰囲気

というわけで家に閉じこもっているので今日はバグを修正していました。
修正したバグの一覧

・曲を再生していると音がならなくなる
・GoogleDriveの接続設定ができない
・Dropboxの接続設定ができない
・再生中の状態をアニメーションにした
・バッファリングの状態をプログレスバーに表示した
・アーティスト名の更新がアルバム名の更新処理になっていて反映されていなかった
・再生中の曲のタイトルをBold指定にした
・アルバムアーティストの表示を灰色にし二行表示にした
・再生リストに追加する際、キャッシュファイルからタグ情報を読み込むようにした。(このせいで追加処理が遅くなってるきがしてる。あまりに問題なら、タイミングを再生時に移動するなどの工夫をするかも)


他にもこんなバグがあるよというのがありましたら報告をして頂けると助かります。


Saturday, August 9, 2014

AudioEffectつらみある

Activityで3画面で作っていたものを、Fragmentにしたため初期化のタイミングがだいぶ変わってしまいました。
そのせいで、AudioEffectへの更新処理が何度も届くバグを入れてしまったようです。

ぱっとみ使っている分には気づかないのですが、端末によっては音が鳴らなくなります。致命的

僕の端末だと数曲流してると突然音だけ聞こえない状況になります。
音が鳴らなくなったーという現象がある方はひとまず利用を停止してください。

Friday, August 8, 2014

Boxnetでもそこそこちゃんと動くようになりました。

ほっといたら動かなくなったり、長時間再生していると再生できなるといった不具合を修正しました。
それから、設定でフォルダの選択ダイアログや、詳細情報で選択中のフォルダやフォルダ使用量をサマリーで表示するように変更しました。

https://bitbucket.org/yokmama/just-player/downloads/JUSTPLAYER3_v4.0_314190008.apk

Thursday, August 7, 2014

Box.netに対応してみました

Box.net のユーザがJUST PLAYERを使っているということなので対応してみました。


Monday, August 4, 2014

Canvasに引いた線にグローエフェクトをつける

今日はメニューの整理をしていましたが、若干飽きてきたので、アルバムビューで表示している円のVisualizerにグローエフェクトをかけてみました。
わかりにくいかもしれないですが、下記の画像のようになります。


グローエフェクトは、PaintにBlurMaskFilterを設定することで表現できます。
実際にはBlurMaskFilterでぼかしをかけることでそれっぽく見せてるだけです。
具体的には次のようなコードでPaintを宣言しておきます。

        float width = 7f;
        float blueWidth = width*2.0f;

        mPaint = new Paint();
        mPaint.setStrokeWidth(width);
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);

        mBlurPaint = new Paint();
        mBlurPaint.set(mPaint);
        mBlurPaint.setStrokeWidth(blueWidth);
        mBlurPaint.setMaskFilter(new BlurMaskFilter(blueWidth/2, BlurMaskFilter.Blur.NORMAL));

ぼかし用のPaintのほうの太さを2倍ぐらいにして、ぼかし幅はその半分ぐらいにしていますが、これは調整していてこれぐらいがちょうど良かっただけなので、もっとぼかしたいというのであれば、BlurPaintのほうの太さをもっと太くし、ぼかし幅も大きくすれば良いと思います。

これをもとに、同じPathに描画を2回してあげれば上記のような画像になります。

            canvas.drawPath(path, mPaint);
            canvas.drawPath(path, mBlurPaint);

Saturday, August 2, 2014

NavigationDrawerのOpenをジェスチャーでは開かないないようにする

NavigationDrawerのOpenがViewPagerのスワイプと被ってるので、NavigationDrawerのジェスチャー処理を無効にしようと思ったのですが、最初はやりかたがわからなくて、DrawerLayoutクラスを継承してOnTouch辺りを強制的にぐりぐりしようかとおもったけど、もっと簡単にやる方法があったので助かった。

mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);

DrawerLayoutクラスにsetDrawerLockModeでDrawerLayout.LOCK_MODE_LOCKED_CLOSEDを設定すると期待していた動きになります。

ちなみに、このフラグは他にも

デフォルトの値、ジェスチャーでOpen,Closeする。
LOCK_MODE_UNLOCKED

ジェスチャーによってOpenしない。
LOCK_MODE_LOCKED_CLOSED

ジェスチャーでOpenしない上、クローズもしない。上のやつだと外部タップで自動で閉じる。
LOCK_MODE_LOCKED_OPEN

ということらしいです。

やっぱり、NavigationDrawerのジェスチャーはOFFにしていたほうが気持ちよく操作できますね。



迷ったら作ってみる

どんな具合になるのか作って実際に使ってみないとわかんないな。
ということで、ひとまず、スワイプによる画面移動、それとNavigationDrawerを置いたままにして、使い勝手が悪いかどうか実装してみました。

apk ink: https://bitbucket.org/yokmama/just-player/downloads/JUSTPLAYER3_v4.0_314190006.apk

注)上記のAPKはKitKatでしか動作チェックをしていないので、ICS、JerryBeansでちゃんと動くか試していません。

このバージョンでは、NavigationDrawerの中にあったイコライザ、AlbumArt画面の移動をスワイプで移動するように変更し、曲の選択だけNavigatioDrawerに残しています。


使ってみておもったこと。
やっぱり、NavigationDrawerの引き出しがスワイプ画面移動と被っていて操作しにくい。
誤動作も頻発する。

解決策として、Drawerのスワイプによる引き出しは無効にして、上部のボタンでOpenするようにしようかとおもっています。
あと、それだけじゃ気付きにくいので、ActionBarにもOpenのボタンを追加しようかと。
ActionBarにボタンが増えるのは嫌ですが。

昨日、他のクラウド上の音楽ファイルの再生アプリをいくつか触ってみて、JUST PLAYERだけしかできていないことを探してみたら、次のようなことが他とは違うと思っています。

・ Cloud上にあるM3U、CUEファイルによるプレイリストの読み込み
・ Cloud上にある音楽ファイルと同じフォルダにある画像をアルバムアートとして適用する。
・ 大きめの音楽ファイルも再生できる。
・ 複数のクラウドを混ぜこぜにして再生リストを作れる。
(もちろん保存も対応するよ)
・ ギャップレス再生ができる






Friday, August 1, 2014

NvigationDrawerとSwaipとUIで悩み中

今日はGooglePlayStoreに公開されている色んな音楽アプリを使ってみました。
理由は、現在開発中のアプリのUIをどうすればよくなるのか悩んでいるからです。


Perk,RMSメーターと、FFTのVisualizerを作った

前からあったけど、ちゃんと説明していなかったし、また見た目もしっかり作りこんでなかったので報告をしていなかったのですが、ひとまずまずまずの見た目が確保できたので報告しておきます。


Wednesday, July 30, 2014

VisualizerのReleaseで苦しみ中

これ、
http://stackoverflow.com/questions/14302825/fatal-signal-11-android-visualizer

Visualizerの生成、破棄を繰り返し行うと落ちる問題で苦しんでる。
Activityの生成時、というかOnResumeでVisualizerを生成し、OnPauseで破棄をするのは一般的な実装だとおもうんだけど、Activityの表示、非表示を何度も繰り返すと上記リンクと同じLogが出力されおちてしまう。
Visualizerを使わないと発生しないので戦犯はVisualizerで間違いないとおもう。

僕がテストしているコードではMediaPlayerの再生を一時停止していても上記問題が発生するのでAudioSesssionが変わったとかそう言う問題ではないだろう。

Visualizerの生成と破棄の間隔が短いと発生するようだ、これは端末によっては発生しないものもあるかもしれない。

Thread.sleep(100)をいれると落ちにくくはなる。


RecyclerViewをICSで使う方法

Android-Lの発表と同時に追加されたRecyclerViewですが、こちらListViewよりもパフォーマンスが良く、またHorizontalScrollとVerticalScrollの使い分けや、GridView、ListViewの使い分けをしやすいといったメリットがあります。
早速つかいたいのですが、Android-Lでないとコンパイルエラーがでるのでどうしたものかとおもっていたけど、解決方法があったのでメモ。

タイトルにはICSと書いていますが、テストをしたのがISC端末なだけなので、KitKatでも多分大丈夫だと思う。

まず、Gradleの指定、こいつをdependenciesに追加。

    compile 'com.android.support:support-v4:20.0+'
    compile 'com.android.support:recyclerview-v7:+'

それから、レイアウトファイルはとくに仕掛けは必要ありません。
    <android.support.v7.widget.RecyclerView
        android:id="@+id/my_recycler_view"
        android:scrollbars="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentTop="true"
        android:layout_above="@+id/controlLayout"/>

こんな感じでいれればよいとおもいます。

だいじなのはAndroidManifest.xmlファイル、こちらは以下の1文を追加する必要があります。

    <uses-sdk tools:node="replace" />

これは、uses-permitsionタグと同じ階層であるルートタグの子チャイルドとして追加してください。また、

xmlns:tools="http://schemas.android.com/tools"

これをいれておかないとエラーになります。
DragListViewをやめて、RecyclerViewにおきかえる作業にとりかかるよー
CardViewもつかえるのかな?

NavigationDrawerとDragListViewは相性が悪いと思う

ListViewを編集可能にするためのDraggableListViewの実装はすぐ思いつく機能の一つだけど、NavigationDrawerと相性がわるいなぁと使っていて思った。
黄色枠のところの判定で、緑のNavigationDrawerをひっぱるつもりが誤タッチでリストの並び替えになってしまったりする。
間隔をひろげればミスはすくなくなるけど、画面を窮屈にするか、別画面にするかの二択だ。

Monday, July 28, 2014

KitKat用にビルド

ブランチ管理が面倒臭いんだけど、一旦Android−Lを別ブランチして、本流をKitKat用にしてみました。

それで、とりあえず動くようになったので、APKを作成しアップロードしました。
ちなみに、Lでしか動かないFABやCarViewは表示されません。
はやくSupportLibraryリリースしてほしいよー。

APKは以下からダウンロード、もしくはベータ版で(こっちは反映されるまで時間かかるとおもう)

https://bitbucket.org/yokmama/just-player/downloads/JUSTPLAYER3_v4.0_314190004.apk

UIをちょこちょこ変更しているところなんだけど、余計なボタン、余計な機能をどんどん省いていくと、見た目よくなるけど、使い勝手は前のに慣れていると使いにくい、特に以前はどこの画面でもPlay、Pause、Skip、Back、Seekといった基本的な操作はやれていたので、それらのボタンがないとすっごく使いにくい。
でもこれらのボタンを配置すると画面が狭くなるので置きたくはない。

標準プレイヤーの場合、それらを割りきっているため、ボタンがある画面とない画面があるのだけど、なんだか、JUST PLAYERで同じようにしてると、使いにくくかんじる。この違いはなんなんだ、、
(標準プレイヤーが使いやすいかどうかは別としてですが。)


Reverbいらないよね?だって動いてないもん

AndroidのAudioEffectにReverbっていう機能があるんだけど、これの効果が全然わからない。

楽器のエフェクターでは、Reverbってのはめちゃかっこいいエフェクトの一つなので、すっごく期待してんだけど、全然効果を感じられないので、使い方が間違ってんのかなぁとずっと疑問におもってました。
また、端末によっては動いているものもあるんだろうと、、
だけど、テスト用に売られているNexusシリーズで動いていることを実感できないとなっては、これサポートする意味あんの?と思う次第です。

ちなみに、公式サイトによると、Reverbは他のEffectとは異なり次のような点で注意しなければならないようです。

1AudioSessionは0で生成しないといけない。
2SendLvelを設定しておかないといけない。
3EffectをMediaPlayerにAttachしないといけない。

上記のルールを守ると次のようなコードになります。

PresetReverb mReverb = new PresetReverb(1, 0);
mReverb.setPreset(PresetReverb.PRESET_LARGEROOM);
mReverb.setEnabled(true);
mp1.attachAuxEffect(mReverb.getId());
mp1.setAuxEffectSendLevel(1.0f);

しかし効果は分からない、あとはMediaPlayerを生成しDataSourceを設定するまえに設定するのか?その後なのか?ぐらいだけど、両方ためしてみたけど効果を感じられなかったです。
そもそも、DataSourceに前に設定とか、後とかの設定が本当に意味があるのだったら、すっごくステート管理が面倒になるのでやりたくはない。
あと、ほかにもフェフェクトとしてEnvironmentalReverbまであるので、これとの組み合わせによる管理も必要だし、ただでさえ、Effect周りは何度もOn/Offをしたり曲をきりかえたりすると稀にフリーズしたり落ちたりするので、これ以上面倒な実装をいれたくないというのが本音です。

こんなのに頭使うぐらいなら、Gain操作をしてReplayGapの実装をしたほうがどんだけ有意義かわからないですよね。
てわけで、Reverb機能は実装しない方向で考えてます。

もし、こうやったら良いという情報があればご一報をください。
そのときは喜んで実装いたします。




Sunday, July 27, 2014

Android-Universal-Image-Loaderの日本語ファイルの扱いでハマる

Android-Universal-Image-Loaderはとっても高機能で積極的に使っているのですが、ファイルは存在するのエラーがでていて困っていました。
下記はそのときのエラーログです。

07-27 13:11:40.254  11037-11104/? E/ImageLoader﹕ /sdcard/Music/supercell%20Discography/supercell%20Discography/1st%20single%20%5B%E5%90%9B%E3%81%AE%E7%9F%A5%E3%82%89%E3%81%AA%E3%81%84%E7%89%A9%E8%AA%9E%5D/cover.jpg: open failed: ENOENT (No such file or directory)
    java.io.FileNotFoundException: /sdcard/Music/supercell%20Discography/supercell%20Discography/1st%20single%20%5B%E5%90%9B%E3%81%AE%E7%9F%A5%E3%82%89%E3%81%AA%E3%81%84%E7%89%A9%E8%AA%9E%5D/cover.jpg: open failed: ENOENT (No such file or directory)
            at libcore.io.IoBridge.open(IoBridge.java:456)
            at java.io.FileInputStream.(FileInputStream.java:76)
            at java.io.FileInputStream.(FileInputStream.java:103)
            at com.nostra13.universalimageloader.core.download.BaseImageDownloader.getStreamFromFile(BaseImageDownloader.java:158)
            at jp.co.kayo.android.localplayer.MyApplication$MyImageDownloader.getStreamFromFile(MyApplication.java:176)
            at com.nostra13.universalimageloader.core.download.BaseImageDownloader.getStream(BaseImageDownloader.java:86)
            at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.downloadImage(LoadAndDisplayImageTask.java:290)
            at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.tryCacheImageOnDisk(LoadAndDisplayImageTask.java:273)
            at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.tryLoadBitmap(LoadAndDisplayImageTask.java:229)
            at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.run(LoadAndDisplayImageTask.java:135)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
            at java.lang.Thread.run(Thread.java:818)

これは、ファイル名の取得処理で日本語処理に誤りがあったからなので修正方法をメモしておきます。

Friday, July 25, 2014

AndroidWearのNotificationで若干ハマりました

MediaPlayerのようなServiceで処理をする場合に表示するNotificationは、Serviceが処理が終わるまでシステムに勝手に殺されないようにするためsetOngoing(true)をNotifiationに設定し、且つContextのstartForegroundでNotificationを表示しないといけません。(注:とはいっても、システムによって殺されにくくなるというだけです)


Tuesday, July 22, 2014

ボタンをFabに置き換えてみた

配色が難しい、
MaterialDesginのガイドラインではLightThemeをベースにした配色例は多くあるけど、DarkThemeの配色例は少ないきがする、だからJUST PLAYERのように黒をベースにした配色の場合のFabの色はどれがいいのか困っています。

旅する配色見本
http://ironodata.info/travel/

このサイトを参考に、プライマリ、アクセント、コントラストの色を参考にとりあえず赤にしてみたけど、しばらく使ってみて違和感がないか調べてみる。

このFabを使ったバージョンはAndroid−Lでないと動かないので、開発中ビルドとしてアップロードできません。
どちらでも動くSupportLibraryがそのうちでるとおもうのですが、しばらくはなさそうです。だからといって、それまでずっとアップロードなしというわけにもいかないので、デザインが一段落したら、Android-L以下でもとりあえず動くようにしたバージョンを作る予定です。
もうすこしお待ちください。


こうしてみると、Fabのアイコンが大きすぎて変だなぁ、色ももうちょっとトーンを落としたほうがよいようなきもする。

※Fabというのは、右下の赤色の丸いボタンのことで、FloatingActionButtonの略です。

Thursday, July 17, 2014

メイン画面のUIをひとまず実装してみた

メインの再生リストを表示する画面を実装してみました。
MaterialDesignに対応するといっても、どこまで実装すればよいのか難しいです。


左上のActionBarのタイトル文字の左側の隙間が微妙にきになる。
カスタムレイアウトをなるべく使いたくないので設定でなんとかならないか工夫しているのですがうまくいかない。
それから下の操作部分をスッキリさせるためにボタンは一個だけにしました。
標準プレイヤーがこうなっているので不都合はないはずですが、早送りボタンをおいたほうが便利なんじゃないのかと思ったりしています。

しかし、両方おいた場合のデザインがださいんですよねー。

■ ▶ hohogehoge ▶▶ 

上記のように▶が複数ならぶので見た目がださい。
(早送りボタンは長押しで5秒スキップを持続する機能です。)

あと、操作部分がびっちり隙間なくくっついているので広告っぽくみえる。
これも隙間をちょっといれたほうがよいのかなと思った。

ボタンのデザインも、MenuButtonみたいにフレームのようなデザインのほうがよかったかなぁ。



Friday, July 4, 2014

Ampache対応しました

Ampacheの実装をしました。
といっても最低限です。
WIFIと3Gでホスト名が違う場合入力しなおしが発生するため面倒です。
利便性を考えれば、WIFI用と3G用で設定を自動できりかえる仕組み、もしくは、コンボボックスなので簡単に切り替えあできるようにしたいところです。

https://bitbucket.org/yokmama/just-player/downloads/JUSTPLAYER3_v4.0_314190001.apk

必要最低限の機能まで実装したので、ひとまずAmpache対応はここまでとして、UIの見直しをしたいとおもっています。
Android−Lが発表され、MaterialDesignの利用が推奨されるようになりました。
ですのでUIはこれを踏襲して実装する予定です。


Friday, June 20, 2014

JUST PLAYER2をベータ版として公開しました

JUST PLAYER2をベータ版として公開をはじめました。

ダウンロードは下記のURLからできます。

https://play.google.com/apps/testing/jp.co.kayo.android.localplayer

ただし、ダウンロードするためにはJUST PLAYERのUserGroupに登録されている必要があります。
登録は以下のサイトから申請できます。

https://groups.google.com/forum/#!forum/justplayer-user

現在、GoogleDrive,Dropbox,SDCard、MediaStoreに対応しています。
これからAmpacheに対応し、その後UIを整えていく予定です。
秋頃までににはなんとか正式リリースしたいとおもっていますが、、テストも山積みですので約束はできません。

Tuesday, June 17, 2014

Artist,Genres,Albumの画像作成中

ちょっと最近仕事が忙しくなって、こちらに手がつけられない状況が続いています。
それでも、数時間ぐらいは当てれるようにやっているのですが、牛歩というか、、
いまとりかかっているのは、MediaStoreの一覧表示処理です。
とりえず、先日一覧表示はできるようになったのですが、ジャンルやアーティスト、アルバムの画像がないものが多いです。
これを見えるようにしたい。
MediaScannerはアルバムアートに関しては、スキャン時にメディアファイルから取得してアルバム情報にアルバムアートのキャッシュのパスを設定しています。
この仕様は助かる反面、コンピレーション・アルバムみたいな複数のアルバムアートが存在する楽曲がある場合うまくありません。
コンピレーション・アルバムの名前で楽曲にタグが設定されているならまだいいのですが、そうでないものは、それぞれ一曲単位でアルバム情報が生成されてしまいます。
メディアストアにはフォルダ単位で情報を管理するものがないので、この部分はプレイリストでフォルダ単位で登録してもらえるとか救済処置があってもよいものですが、、
これはまぁ、仕方がないんだけど。
だけど、アーティスト等はそもそも画像をもっていないので、どうしようもないです。
なので、現状アーティスト、ジャンル、プレイリストは真っ黒です。
そこで、該当する楽曲から複数のアルバムアートを抜き出して2x2程度の四角に敷き詰めるように画像を作成しようと苦労しています。
とりあえず、画像を合体するだけならなんとかできるようになりました。
だけど、処理速度が遅くいまいちイケてません。
なんとか、高速にできるように工夫しているところです。

Saturday, June 7, 2014

MediaStoreからの選択機能を追加

MediaStoreというのは、Andoridが管理している曲データベースです。
AndroidはSDカードを常に監視し、SDカードに曲が追加されたらその情報を拾い出し、Android上の曲データベースに追加します。
情報はインデックス化され、アルバム名、アーティスト名で検索が可能になります。

通常、Androidで音楽アプリをつくる場合はこのデータベース(MediaStore)を参照するのがもっとも手っ取り早いのですが、独自の仕様であるためメディアのフォーマットによって独自の情報があっても捨てられてしまうのが残念なところです。
旧作のJUSTPLAYERではこのMediaStoreをベースに実装をしているため、DropboxやAmpacheの情報を無理やり合わせていました、そのため面倒な問題もでてたので、JUST PLAYER2では、MediaStoreはあくまでひとつの選択肢とし、基本はそれぞれの曲情報を大事にする方針です。

そういう理由があって、MediaStoreからの曲選択の実装が遅れているのですが、次の実装がAmpacheになるので、Ampacheの実装でも共通するMediaStoreの実装をしてみました。
アルバム、ジャンル、アーティスト、メディアから曲選択ができるようになっています。
まだ作り込みが甘く、アルバムアートに関しても工夫がなく、処理に関してももたつくところもあり、階層表示なども考慮していないので使いにくいかもしれません。

https://bitbucket.org/yokmama/just-player/downloads/JUSTPLAYER3_v1.0_060701.apk


Friday, June 6, 2014

曲の追加、置き換えを追加してみました

MediaStoreの選択画面の実装に入る前に、プレイリストやフォルダを選択した際に、今の再生リストを全置き換えとなっているところを、「置き換え」、もしくは「追加」の選択ができるように変更しました。
これに伴い、一曲単位での追加も可能にしました。
けっこうリファクタリングが多くなったので、ここで一旦リリースします。

https://bitbucket.org/yokmama/just-player/downloads/JUSTPLAYER3_v1.0_060601.apk

あと、UIまわりも見直し中です、NavigationDrawerのなかに設定とイコライザをいれました。
設定はまだ未実装だけど、イコライザは基本どこの画面からもいけるようになります。

だいぶ使い勝手がよくなってきてると思うんだけどどうですかね。

Wednesday, June 4, 2014

「Wake lock not active」これが頻繁にでる

これなんででるのかなぁーと思いつつ、特に実害がないのでほっといてるんだけどやっぱり気持ち悪い

 java.lang.IllegalArgumentException: Wake lock not active
            at com.android.server.power.PowerManagerService.updateWakeLockWorkSourceInternal(PowerManagerService.java:794)
            at com.android.server.power.PowerManagerService.updateWakeLockWorkSource(PowerManagerService.java:780)
            at com.android.server.power.PowerManagerService.updateWakeLockUids(PowerManagerService.java:761)
            at android.os.IPowerManager$Stub.onTransact(IPowerManager.java:103)
            at android.os.Binder.execTransact(Binder.java:404)
            at dalvik.system.NativeStart.run(Native Method)

MediaPlayerを使用して、ギャップレス再生を実現しているのだけど、setDataSourceだけしているMediaPlayerにもWakeLock指定をしているのが原因なのかな?
とおもったので、試しにstartするタイミングでWakeLock指定をするように修正してみたのですが変化なし、
Lock周りの実装といったら、Service起動時にWakeLockを取得しているところがあるぐらいだけど、あれは過去の実装でも問題はなかった。

   
mMediaPlayer.setWakeMode(mMediaPlayerService.getApplicationContext(),
                        PowerManager.PARTIAL_WAKE_LOCK);

この処理は今回の実装からはいったのでこれが一番あやしい。
ためしにこれ外してみたんだけど、

それでもでる、なんだこれ?
ちなみに端末を変えたらでなくなりました。
機種依存なんかなぁ、気持ち悪い



Dropboxに対応してみました

GoogleDrive対応の延長になるのですが、Dropboxにも対応しました。
SDKが新しくなってたけど基本的な使い方は同じなので対応は簡単でした。

GoogleDriveと比較して、Dropboxのほうがレスポンス遅い気がします。
一度再生をしてしまえば早いのですが。。

あと、M3Uの対応で間違いがあったので修正をしておきました。
M3Uには#EXTINFという行があって、当初はこれは、ただのコメント的なものでフォーマットは決まりないのかとおもってたけど、
どうやらちゃんと決まりがあるようなので、安心してこの情報からタイトルとアーティスト名を取得するようにしました。
ローカルストレージの場合は、MediaStoreから取得するのでこれはみてないです。
だけど、GoogleDriveや、Dropboxの場合はここに設定をしておかないとファイル名がタイトルになってしまうのでできれば設定しておいたほうがよいでしょう。

Dropbox対応のAPKは下記からダウンロードできます。

https://bitbucket.org/yokmama/just-player/downloads/JUSTPLAYER3_v1.0_060401.apk

SDカード、GoogleDriveの曲選択画面をリファクタリング中

次はDropbox対応をする予定です。
そのためには、いまあるプログラムを流用しやすくするためクラスの設計の見直しをしなければなりません。
理想としては、ファイル選択系の画面、メディア選択系の画面で派生します。
SDカード、GoogleDriveはファイル選択系です。
この2つはローカル上のファイルか、ストリーミングのファイルの違いがありますので流用できる箇所はファイル選択画面のUI部分だけなのですが、
Dropboxの場合は、GoogleDriveにかなり近いため流用箇所が多くなります。
大きな違いとしては、GoogleDriveはファイルストリームの取得が専用のHttpRequest、HttpResponsを使うのに対し、Dropboxは標準のHttpアクセスをつかうことになる点でしょう。
だから、Dropbox対応が完了すれば、他のBox.Net、SkyDrive、OwnCloud等の対応はたやすくなるとおもいます。
なので、ファイル選択系の画面はDropboxで一旦終了する予定です。
その後は、メディア選択系の画面の実装になります。
こちらは実ファイルのフォルダの情報を公開はしてなく、アルバム、アーティスト、メディアのように各メディアの検索をサポートしているデータになります。
対象になるのはローカルのメディアストア、あとAmpacheですね。
Ampache対応をするのであれば避けては通れない実装になります。
作り込みも多いのでけっこう時間がかかるとおもいます。

あと地味ですが、曲の先送り、巻き戻しの指定でIndexに1をプラスして移動していましたが、今後、ストリーミングがキャッシュされていないメディアは除外するといったオプションを追加する予定ですので、1をプラスではなく次に大きい、あるいは次に小さいというような指定の仕方に変更しないといけないです。
地味だけど、SQLの組み立てが面倒くさくなるので面倒くさい実装になりそうです。


Monday, June 2, 2014

GoogleDriveのRange指定がちゃんと動かないのはもしかして、、

長らくGoogleDrive上のファイルでRange指定をするとフリーズしてしまう問題で苦しんでいるのですが、問題の起きているファイルには特徴があることがわかりました。

まず、ファイルのサイズが大きすぎる件。
テストで使用しているファイルは再生時間が1時間以上のファイルです。
長いもので2時間超の音楽ファイルなのですが、これらのファイルはローカルでは正常に再生できています。
ストリーミング再生でもRange指定で簡単にシーク位置まで移動してくれるものとおもっていたのですが、どうやら、これWebサーバーによってはうまくいかないのかもしれないです。というのも、これDropboxやAmpacheでは経験してないんですよね。
ちなみに、フリーズしている箇所はGoogleDriveAPIのHttpRequestに対して、Executeを実行している箇所です。

Range指定をした場合は、ときどきこの場所でフリーズするんです。
うまくいく場合もあります。これが謎、なのですが。

うまくいく場合は、一発目に限るです。
一度再生用のストリーミング処理をしている最中に、Range指定をするとフリーズします。
この流れですが、MediaPlayerによって再生中のコネクションを切断するのは、Range指定されたリクエストが発行された後のようなので、これが問題になっているのかもしれません。

あと、プログラム側でも考慮するべき箇所がありました。
JUST PLAYERでは状況を把握するために定期的に isPlaying や getCurrentPosition、 seekToなどを行っています。
これ、Prepareされるまえに呼ばれる可能性がありました。
さすがに seekToはなさそうですが、 isPlayingや getCurrentPositionなどは状況をチェックする際に呼ばれます、この処理のためにRange指定のリクエストがどうやら動いているようなんですね。
てことは、頻繁にリクエストが発生すると、GoogleDriveは短い時間の間に何度もリクエストがくるとエラーを返すようなので、これはまずい感じがします。
ですので、とりあえずPrepareが終わってない場合は0なりFalseを返すなりの処理にしておきました。

このような処理をすることで少しは動作が安定したようにみえます、曲の選択でも簡単にフリーズしていたけど今はそれほど問題はおきていません。
もちろん、長いファイルの曲の移動では問題がおきていますので、これは今後の課題になりそうです。

下記のリンクは現時点の最新モジュールです。
シャッフルのロジックの修正、上記問題の修正、MimeType読み込みの修正、MinSDKを14にするといった修正がはいっています。
あと、共有ドライブの機能は動作が確認できたので一旦無効にしています。
(共有ドライブのリスティングが遅いので、テストだとイライラするため、これは将来オプションですね。)

https://bitbucket.org/yokmama/just-player/downloads/JUSTPLAYER3_v1.0_060201.apk

#口調が砕けてきて読みにくい文章になりつつあります。すみませーん。


Android アプリのクライアント ID登録の罠に注意

今開発で使っているのはRatinaMacBookProなんだけど、
最近調子悪くて、USBの認識がブツブツ切れてイライラしたり、ときどきスタンバイからの復帰で電源ボタンしかきかずキーボード、トラックバッドが無反応になったりと、
まるで明日開催されるWWDCで新しいMacbookが発売されたらそれを買えとプレッシャーかけてきてる雰囲気を感じています。

今日だってあんまりにもひどいから、古いMacBookAirを掘り出して開発をしているんですが、コーディングをしていざテストをしようとしたら、GoogleDriveの認証がうまくうごかない。

あれぇー先日修正したのになんで、、
もしかして、2段階認証はうまくいくようになったけど、1段階のは逆にだめになったのかなぁーと疑っていたのだけど、ログをみても怪しいところはない。

よーく考えてみて、APIConsoleをみてみたら、この開発PCのAPIキーが登録されていない?

これ先日登録した気がすんだけど気のせいかなぁーと再度登録してみたらエラーがでてきました。

実は今登録されているAPIキーはRatinaのデバッグ用のキーストアで登録をしているのですが、同じパッケージに対してキーストアは一個しか認められないみたいなので、、このPCのキーストアの登録はエラーになっていたようです。

登録できていたというのは僕の見間違いのよう。

てことは、KeyStoreなくしたら最悪ですね、、チームで開発するときにも気をつけないといけないでしょう。

PCを買い換えるときにもDebugキーストアもちゃーんともってこないとテストで苦労するっていうことを知りました。

新しいRatinaMacBookProはよこい。


Sunday, June 1, 2014

GoogleDriveのRange指定が倒せない。

GoogleDriveには、OwnFileとShareFileの二種類へのアクセスがあります。
通常のファイルアクセスではOwnFileだけなのですが、検索条件にsharedWithMeをつけるとShareファイルも検索結果に現れます。
こうして取得したファイルはどちらも同じような扱いができるのかと思っていたのですが、なんとなくしっくりきていないです。
理由は、sharedWithMeで取得したファイルのフォルダ一覧取得では、特定の拡張子のファイルのMimeTypeがOwnFileのフォルダとは違ったり、リクエストに対するレスポンスのやりとりが違ったりなんだかよくわからないです。
今嵌っているのは、そういう問題によってRange指定したリクエストが突然切断されまた、場合よってはフリーズすることがある不具合です。
これを解決しない限りリリースは先になってしまいそうなんですが、うまい回避方法がないものか。

とりあえず、GoogleDrive上におかれたプレイリストに対応しました。
プレイリストは m3u とCueファイルになります。

https://bitbucket.org/yokmama/just-player/downloads/JUSTPLAYER3_v1.0_060101.apk

Saturday, May 31, 2014

ストリームキャッシュ機能をとりあえず実装

今日は一日休みだったのでプログラム充してました。
とりあえず、実用レベルまでキャッシュ機能を実装したので記念上げです。

現時点の実装は以下のとおりです。

・Range指定のストリーミングでない場合に限りキャッシュの作成を行う。
(シークバーなどでバッファを先読みすると、内部でRange指定でHTTPリクエストがくるんだけど、その場合はキャッシュ化はしないよっていう意味)
・キャッシュはキャッシュフォルダに作成され、再生時に利用されます。
ただし、このファイルは起動時に3日前のものを消す仕様になっています。

将来的には、Range指定されてもキャッシュ化し、再生時に最新日付を設定することで消される対象から除外するといった処理をする予定です。
あと今回はRatingを統一する予定なので、Ratingにも比例して消されにくくしたいと思っています。
あと、要望であった、キャッシュフォルダを設定で変更出来るようにするなど

https://bitbucket.org/yokmama/just-player/downloads/JUSTPLAYER3_v1.0_053102.apk

GoogleDriveすごい、、かも

今日の予定である、GoogleDriveAPIからのStreaming処理の部分をDropboxやAmpacheといった他のクラウドデータでも使える用に、Creator、Strategyパターンでリファクタリングしました。
このあとキャッシュ化処理を実装しようかとおもったんだけど、ちょっと疲れたので、GoogleDrive共有フォルダへのアクセスが可能かどうかしらべたところ、できましたね。
これは、すごい。
Dropboxとか他のクラウド・ストレージの場合共有フォルダはいくつか制限があるもんだけど、これはあんのかなぁ?
スピードも早いし快適すぎるよ。

共有フォルダ対応したバージョンをアップロードしておきました。

二段階認証時の処理対応

GoogleDrive対応がやっつけ仕事だったので、二段階認証や認証でなにか問題があってエラーがおきたときに無限ループのような状態になってました。

05-30 19:44:35.425      333-335/? D/dalvikvm﹕ GC_CONCURRENT freed 865K, 11% free 14926K/16647K, paused 1ms+5ms
05-30 19:44:35.441    4161-4172/? I/GLSUser﹕ GLS error: BadAuthentication
05-30 19:44:35.441    4161-4172/? V/GoogleLoginService﹕ Returning error intent with: ComponentInfo{com.google.android.gsf.login/com.google.android.gsf.login.LoginActivity}
05-30 19:44:35.464  17779-17905/? E/MusicStreaming﹕ Received null auth token.
    android.accounts.AuthenticatorException: Received null auth token.
            at com.google.android.music.sync.google.MusicAuthInfo.getAuthToken(MusicAuthInfo.java:42)
            at com.google.android.music.sync.api.SignupClient.checkInviteStatus(SignupClient.java:86)
            at com.google.android.music.tutorial.SignupStatus$SignupCheckService.onHandleIntent(SignupStatus.java:308)
            at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.os.HandlerThread.run(HandlerThread.java:60)
05-30 19:44:35.464  17779-17905/? I/CheckMusicStoreAvail﹕ No verified accounts found
05-30 19:44:35.496  17779-17905/? I/CheckMusicStoreAvail﹕ Starting account signup check
05-30 19:44:35.558      186-213/? I/ActivityManager﹕ Displayed com.google.android.gms/.auth.login.ShowErrorActivity: +226ms
05-30 19:44:35.574  16430-16430/? D/OpenGLRenderer﹕ Flushing caches (mode 0)
05-30 19:44:35.605  16430-16430/? D/OpenGLRenderer﹕ Flushing caches (mode 0)
05-30 19:44:35.628    4161-4172/? I/GLSUser﹕ GLS error: BadAuthentication
05-30 19:44:35.636    4161-4172/? V/GoogleLoginService﹕ Returning error intent with: ComponentInfo{com.google.android.gsf.login/com.google.android.gsf.login.LoginActivity}

原因は、エラーが起きた時に、理由の含まれたExceptionを渡して再度ログインを試みるのですが、この際別のアプリに連携します。
二段階認証だとこの処理でブラウザアプリに連携しそこで認証コードを入力して戻るという処理なのですが、このとき新たにActivityが生成されるので、また認証処理を実行してしまうというループになっているようでした。
もどってきてもきちんと処理をうけとれるようにAndroidManifest.xmlでandroid:launchMode="singleInstance"にすることでとりあえずの処置をしました。
この認証処理は、OnStartとかで実装するのではなく、ボタンなどのトリガーで呼び出すように実装するのが正しのかとおもいます。

ちなみに、上記ログに関連する情報は下記にもあります。
http://stackoverflow.com/questions/12929569/error-while-trying-trying-to-use-oauth2-accountmanagerfuture-to-authenticate-w

修正したアプリはこちらにアップしました。

https://bitbucket.org/yokmama/just-player/downloads/JUSTPLAYER3_v1.0_053001.apk

いちおうGoogleDriveアプリと連携できたので、今後はStreaming処理に手を入れていく予定です。
今後のマイルストーンは以下のように進めます。

・ストリーミング処理の再構成
・ファイルキャッシュの導入
・画面フロー時の処理を見直し
・GogleDriveファイル選択画面のUIをリファクタリング
・イコライザー設定のバックアップ機能追加
・ブックマーク機能の検討
・その他クラウドへの対応

ちなみに、要望にありましたがBox.netは難しくないのでやりましょう。
SkyDrive(OneDrive)のほうはAndoridからアクセスできるかどうかから調査しないといけないので、できるとはまだ明言できないんだけども。



Wednesday, May 28, 2014

記念上げ

実はこっからが大変なんだけど、ひとまずGoogleDriveの音楽を再生できるようになったので記念上げ。

GoogleDriveのフォルダ内の音楽を再生することしかできません。
ラジオボタンでフォルダ選択、プレイリスト選択は意味ないので注意です。
あとキャッシュ化もしていないです。
これはこっちのほうがいいっていう人がいるかもしれないけど。


https://bitbucket.org/yokmama/just-player/downloads/JUSTPLAYER3_v1.0_052801.apk

クラウド対応始めました

Equalizer処理、Shuffle,Repeat、早送りの対応が終わりだいたい音楽プレイヤーとして形になってきたので、次はクラウドデータの対応をはじめることにした。

クラウド対応といっても、どのクラウドデータに対応するか悩むところです。
最終的には、Dropbox,GoogleDrive,Ampache,OwnCloud,SkyDrive(OneDrive)辺りには対応をしたいなとおもっているのですが、どれからにしようかな。

モチベーションを維持するためにはやったことないところから手をつけていきたい、そういうわけで、GoogleDriveかSkyDriveにしよう。
で、SkyDriveだけどちょっと調べたところ、最近名前がOneDriveになったようですね、OneDriveってUbuntuOneにのってるアレかとおもってました。違った。
SkyDriveは以前オープンソースのライブラリを見つけたのでそれで試したことがあるんだけど、APIが古くなっているのか動作確認がとれなかったです。そういう状況だったのでOneDriveにはとても対応してるとはおもえないし、公式サイトをみてもどうやってアクセスすればいいのかイマイチわからない感じでした。
というわけで、まずは手始めにGoogleDriveから対応することにします。

GoogleDriveは最近GooglePlayServiceからアクセス出来るようになったし、認証処理などもお手軽にできるようになったので、JUST PLAYERのクラウドデータとしては標準で装備してもよいのかなとおもっています。
これが実装できたら、インターフェースを統一して他はプラグインという形で提供できればいいなぁ。



Tuesday, May 27, 2014

Shuffleの実装

Shuffleの実装は意外と難しい。
Equalizerの実装は納得はしてないけど、とりあえずこれ以上掘ってもわからないので一旦ペンディングすることにしてRepeatとShuffleの実装にとりかかることにした。

Repeatはそんなに難しくない、1曲リピートはOnCompleteのときにSeekで0に戻せばいいだけだし、RepeatAllは最終の曲が再生され次の曲がないとき一曲目から再生するようにするだけでよい。
ただ、JUST PLAYER3にはBookmark機能があるのでその分実装が少し複雑になるけども。
まぁ、これはいいとして問題はShuffle。
Shuffleは、ShuffleをOnにしているときに再生順がランダムになるようにする機能だ。
このランダムというのが先読み機能と相性が悪くて、次の曲が何を再生するのかわからないようなShuffleは実装できない。
それに、一度再生された曲が何度もでてくるのもいただけない。
なので、再生済みフラグを設定し、フラグのたっていない曲から次の曲をランダムに選ぶというのが簡単に思いつく実装だとおもう。
前バージョンのJUST PLAYERはこの方法を取り入れていた。
しかし、この方法には欠点があり、プレイリストの数が数千曲もあると、再生後に実行されるシャッフルでもたつきが発生し、折角ギャップレス再生をしていても意味がないものになってしまう。
なので、これをなんとか解決したいと思っていた。
JUST PLAYER3ではそのため、プレイリストの曲順とは別に再生順用の曲順をプレイリストに設定し、シャッフルでそれを一遍に変更することにした。
このシャッフルの設定は曲の登録後に毎回設定することで見かけじょうShuffleされているようにみえるとおもう。
ただ、これでも問題があるとおもう。
Shuffle自体のアルゴリズムだ、既ににあるプレリストに曲を追加した場合、再生中の位置から以降の曲をシャッフルするのが自然だし、まだ一度も再生をしていない状態のプレイリストをShuffleすると一曲目からシャッフルされるべきだし。
数万曲とかのShuffleをしても高速に曲順を設定できるべきだし。
そう考えるとけっこう複雑になってしまう。
実際にShuffleの実装は思った以上に実装ステップ数が多くなってしまったのでバグが潜んでいるのではないかとちょっと心配。

https://bitbucket.org/yokmama/just-player/downloads/JUSTPLAYER3_v1.0_052701.apk






Monday, May 26, 2014

BassBoostとEquqalizerは同時に有効にできない

もしかしたらこれはNexus4が悪いのかもしれない。
もしかしたらこれは、僕のNexus4だけが悪いのかもしれない。

とにかく、BassBoostとEqualizerは両立できないようなので、Equalizerを有効にする場合は一旦BassBoostを無効にするようにした。そして逆も然り
これをするようにしてから、安定して動作をしているようにみえますので、ひとまず開発途中のバージョンをアップロードしました。

現在のところm3uファイルもしくは、cueFile、あとフォルダ指定による音楽の再生しかできません。
AudioEffectは右上の再生ボタンあるいはアルバムアートをクリックすると移動するプレイ画面から、右下のボタンで移動できます。
(添付のスクリーンショットはEqualizer変更画面です。)

 ですが動作確認はNexus4(日本語)でしか実施していません。
他の端末とか、日本語以外の環境ではなにか不都合がおきるかもしれませんが、動作に問題があればご連絡ください。

あぁ、それと、JUST PLAYERのソースコードをPlayStoreにアップロードしている輩がいます。
このアプリに関しては僕は一切関知しておりません。
きちんとバグを修正しているのであればよいのですが、、もしウィルスでも混入しているのでしたら問題です。

下記のアプリは許可なく無断で登録されたものなので、くれぐれもご注意ください。
https://play.google.com/store/apps/details?id=com.illusion.localplayer


PresetReverbは特別なんですか。そうですか。

Visualizerのリスナー内でgetEnabledを実行される前にreleaseをしてしまうと、リスナー内でgetEnabledをした際に意味不明なダンプを出力して落ちてしまう。
とくにこれ、OnDestoryやOnPauseなどでやっていると注意、リスナーモードをNONEに設定しても飛んでくるので。
ということなので、Visualizerのインスタンスにnullを設定することで、リスナー内の処理を実施しないようにしました。
いちおう、これで落ちにくくはなった。その後調子にのって、他のAudioEffectも実装し、PresetReverbまで実装したところで、またまた例のダンプが頻繁に発生するようになってしまいました。
内心またかぁ、まったく。。AudioEffect難しい、、もうこれEquqlizerだけ使えるよう程度にしようかなとおもったりもします。

調べていくと、どうやらPresetReverbはちょっと特別らしい。
たしかに、以前からこれ全然効果ないしおかしいなぁとと思っていました。

公式のリファレンスをみると、下記の様に書いてあります。


The PresetReverb is an output mix auxiliary effect and should be created on Audio session 0. In order for a MediaPlayer or AudioTrack to be fed into this effect, they must be explicitely attached to it and a send level must be specified. Use the effect ID returned by getId() method to designate this particular effect when attaching it to the MediaPlayer or AudioTrack.

Creating a reverb on the output mix (audio session 0) requires permission MODIFY_AUDIO_SETTINGS
これみると、PresetReverbはAudioSessionを0で生成しないとだめって言ってる、しかも、その場合、MODIFY_AUDIO_SETTINGSのパーミッションも有効にしないといけないよって。 たしか、ほかのAudioEffectはAudioSessionを0で使うのはDuplicatedになっているので盲点でした。ようするに、PresetReverbだけ特別扱いしないといけないと、、そういうわけです。 現在、ServiceとActivityで処理をしているので、AudioSessionの使い分けはめんどくさいことになりそう。やっぱり、これがまた後々新たな面倒の種になるとと厄介なので、せっかく前回Activity側でもAudioEffectを持つようにしたけど、それはやめて、Service側が持つものだけにし、アクセスはAIDL経由で行うようにしたほうが管理しやすいきがしてきました。 あぁ、めんどくさい。また修正か。。

Friday, May 23, 2014

Equalizerのもつ位置をもとに戻した

ずっと頭をいためていた例の不具合に関して解決の糸口がみえてきた。
つまり、まだ解決はしていないけど、どうしてこのようなログが吐出されるのかという点で類似する不具合から想像しているだけにすぎないのだけど。

昨日分かったことを並べていくと、
まず、現状問題となっているであろうと予測した「MediaPlayerの生成を何度もしないようにする。」という修正をやってみた。
これまで、曲の切り替えなどで毎回MediaPlayerを初期化していたのは、Resetして再利用するときに下手してStatusエラーがでちゃうのが不安だったので、面倒くさいからっていう理由でした。やはり、そういうことを面倒くさがらずに、一回使い終わったらちゃんと状態をみてResetをし、その後曲を設定するというように変更。
プログラム側からそのような処理を隠蔽するため、中間クラスとしてGaplessMediaPlayerというクラスと、その中で保持される、MediaPlayerHolderというMediaPlayerへの機能の移譲を行うクラスをもつようにした。
こうすることで、MediaConrollerクラスはスッキリした実装になったとおもう。
その後、きちんと動作するようにテストを実施したのですが、ここで新しいバグが発生した。
いままで以上に簡単にEqualizerの設定画面から戻るときに落ちるようになったのです。
しかも出力されるLogCatのパターンも同じ。
前よりひどくなったので、これはなにか変なことになってないかとジィっとプログラムをみてみたところ。一つ見つけました。
それは、Visualizerの解放の順番

間違ってる例
onPause()にて
mVisualizer.setMeasurementMode(Visualizer.MEASUREMENT_MODE_NONE);
mVisualizer.setEnabled(false);
mVisualizer.release();
mVisualizer = null;


正しい例
onPause()にて
mVisualizer.setEnabled(false);
mVisualizer.setMeasurementMode(Visualizer.MEASUREMENT_MODE_NONE);
mVisualizer.release();
mVisualizer = null;

そう、setEnabledの設定順番が間違っていた。
これのせいで、Visualizerのリスナー処理のなかで、visualizer.getEnabled()を呼んでしまい例のダンプが発生していました。
LogCatの状況ではそれが原因にみえなかったのでわかりにくい。
すでに、Releaseで解放されてしまったVisualizerクラスに対してgetEnabled()をしちゃてているので、あのようなダンプにつながったのだとおもいます。
ということは、これまで悩ませていた不具合も、MediaPlayerに関連するVisualizer,Equalizer等でRelease済のものに対してなにか処理をしているのかもしれない。

しかし、おかしいのは上記の実装は、MediaPlayerの初期化の修正の前からのものです。
なので、発生するなら以前からずっと同じように発生しているはずなのですが、、

とにかく、同様のことをやっていないかプログラムを見直すことにします。




Thursday, May 22, 2014

Equalizerをもつ位置について

長いこと問題として認識しつつも放置していたEqualizer使用時の問題について。
問題をまず整理しておくと、

MediaPlayerを管理するServiceと、それにEqualizerの設定を変更する為、Equalizerを別にもつActivityクラス。

EqualizerはMediaPlayerにAttachする必要があるため、MediaPlayerのAudioSessionIDが必要になる。

最初の実装では、ServiceからAIDLによってMediaPlayerのAudioSessionIDを取得し、Activity側が保持するEqualizerにAttachをしていた。
このとき、優先度を上げるためPriorityをService側が保持するEqualizerよりも高くすることで一旦はうまく動作するようなった、ようにみえていた。
しかし、テストでActivity側で設定したEqualizerをsetEnabledでTrue,Falseを繰り返し行うと、稀に落ちる不具合が発生することに気づく。

当初この問題は、Equalizerのノイズに関連する問題なのではと思っていたため、原因の追求は後回しにし、まずはノイズ対策をしていたのだが、ノイズ対策をした後にもこの問題が残っているため。この問題は関連性のないものだと再認識することになった。

昨日の時点で、とりあえず問題をややこしくしているEqualizerをServiceとActivityで別々のものを使うという点に着目し、これを一旦やめて、Service側でもつEqualizerだけにし、Activity側はEqualizerの状態をAIDL経由で取得する方法に変更してみた。

結果、落ちる不具合はかなり改善された、通常使いではほとんど落ちることはないと思われる。
しかし、やはり落ちた。
setEnabledで繰り返しTrue,Falseの切り替えを行い、その後曲の切り替えを行うと落ちる症状が確認された。
狙ってテストをするとかなりの確度で発生する。
この落ちたときに出力されるログは、修正前のログと酷似しているためおそらくこの問題にはEqualizerが関連していると考えられる。

この問題を考察すると、曲の切り替え処理に問題があるのではと考えらえる。
現在の実装では曲の切り替え時にMediaPlayerを一旦破棄し、再生成をしている。
このときAudioSessionIDが新しく生成されるので、ひょっとしたらこれが問題なのかもしれない。
AudioSessionIDが再生成されないように、工夫してみようとおもう。
そうなると、この修正の前に行ったEqualizerのもつ位置の変更はあまり関係がなかったのかもしれない。
一旦この修正を行い落ち着いたら、再度EqualizerをActivity側に移動してみようとおもう。








Wednesday, May 21, 2014

ノイズは除去できただけど

大きい音楽ファイルをシークし、その後再生時に”ジッ”というノイズが入る問題。
Equalizerを設定している場合に限り発生していたが、結局のところSeekが完了するまで、setEnableでFalseにしておくことで回避することにした。
根本的な解決ではなく回避をした理由であるが、いくつかテストをしてみた結果、大きいファイルの場合はノイズが発生してしまうようだ、これは端末に依存する問題なのかもしれない。しかし、他の端末でテストをしていないのでその点に関しては報告できる情報はもっていない。

これに関しては一応解決したことにする、しかしまた新たな問題が発生している。
発生しているというと、今回対処をしていたノイズの不具合の後に発覚していたように思われるかもしれないが、実は以前から発生していて、こちらも原因を調査しないといけない不具合の一つだった。
説明が後回しになってしまったが、不具合の内容というのは、何度もイコライザーをOn,Offをしているとアプリが強制終了してしまうという、致命的な問題である。

次のログは、強制終了時に発行されるログを抜粋したものだ

05-21 10:37:23.013    2221-2221/jp.co.kayo.android.localplayer3 D/MediaController﹕ AudioSessionId = 856
05-21 10:37:23.063  23929-23961/? D/audio_hw_primary﹕ out_set_parameters: enter: usecase(0: deep-buffer-playback) kvpairs: routing=2
05-21 10:37:23.853      183-183/? W/SurfaceFlinger﹕ couldn't log to binary event log: overflow.
05-21 10:37:24.483    2221-2221/jp.co.kayo.android.localplayer3 A/libc﹕ Fatal signal 11 (SIGSEGV) at 0x00000002 (code=1), thread 2221 (id.localplayer3)
05-21 10:37:24.583      181-181/? I/DEBUG﹕ *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
05-21 10:37:24.583      181-181/? I/DEBUG﹕ Build fingerprint: 'google/hammerhead/hammerhead:4.4.2/KOT49H/937116:user/release-keys'
05-21 10:37:24.583      181-181/? I/DEBUG﹕ Revision: '11'

<中略>

05-21 10:37:24.843      764-849/? W/InputDispatcher﹕ channel '42675ea8 jp.co.kayo.android.localplayer3/jp.co.kayo.android.localplayer3.MainActivity (server)' ~ Consumer closed input channel or an error occurred.  events=0xd
05-21 10:37:24.843      764-849/? E/InputDispatcher﹕ channel '42675ea8 jp.co.kayo.android.localplayer3/jp.co.kayo.android.localplayer3.MainActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
05-21 10:37:24.843      764-962/? W/MediaFocusControl﹕ RemoteControlClient died
05-21 10:37:24.843    1822-1897/? V/Avrcp﹕ New genId = 111, clearing = 1
05-21 10:37:24.843      764-962/? W/MediaFocusControl﹕ AudioFocus   audio focus client died
05-21 10:37:24.843      764-962/? I/MediaFocusControl﹕ AudioFocus  removeFocusStackEntry(): removing entry for android.os.BinderProxy@42c7ea90
05-21 10:37:24.843     764-2017/? W/InputDispatcher﹕ Attempted to unregister already unregistered input channel '42675ea8 jp.co.kayo.android.localplayer3/jp.co.kayo.android.localplayer3.MainActivity (server)'
05-21 10:37:24.843    1822-1897/? V/Avrcp﹕ New genId = 112, clearing = 1
05-21 10:37:24.843  23929-23963/? W/AudioPolicyManagerBase﹕ unregisterEffect() unknown effect ID 857
05-21 10:37:24.843     764-1054/? I/ActivityManager﹕ Process jp.co.kayo.android.localplayer3 (pid 2221) has died.
05-21 10:37:24.843     764-2017/? I/WindowState﹕ WIN DEATH: Window{42675ea8 u0 jp.co.kayo.android.localplayer3/jp.co.kayo.android.localplayer3.MainActivity}
05-21 10:37:24.853     764-1054/? W/ActivityManager﹕ Force removing ActivityRecord{4268c988 u0 jp.co.kayo.android.localplayer3/.MainActivity t51}: app died, no saved state
05-21 10:37:24.873      186-186/? D/Zygote﹕ Process 2221 terminated by signal (11)
05-21 10:37:26.083      764-962/? W/InputMethodManagerService﹕ Got RemoteException sending setActive(false) notification to pid 2221 uid 10138
05-21 10:37:26.093      976-987/? W/Binder﹕ Caught a RuntimeException from the binder stub implementation.
    java.lang.NullPointerException
            at android.inputmethodservice.IInputMethodWrapper.setSessionEnabled(IInputMethodWrapper.java:280)
            at com.android.internal.view.IInputMethod$Stub.onTransact(IInputMethod.java:129)
            at android.os.Binder.execTransact(Binder.java:404)
            at dalvik.system.NativeStart.run(Native Method)


あまりに長いので途中は略したが、中身はダンプログになっている。

現時点の考えでは、MediaPlayerを2つもち、それを交互の使用していることと、Equalizerに設定するaudioSessionIdに問題が起因しているのではないかと考えている。
今日の作業はまず状況を整理してみようとおもう。


Tuesday, May 20, 2014

僕とFlacとの格闘

Flacのような長い音楽ファイルの再生にAndoridは特化しているわけではない。とくにFlacの場合CueSheetにも対応していないので、自前で頭出しを実装する必要がある。
これは、僕とFlacファイルとの格闘を、今後この問題が解決し後に振り返るためのメモである。

Day1-Day8
Day1〜Day8としたけど、実際何日たったかなんて覚えてない。
メモをしないといけないと気づいたからだ。そしてそれが今日である。
事の発端は、ある長い音楽ファイルである。
この音楽ファイルはファイルフォーマットはMP3だが、ファイルサイズが1G近くもあり、再生時間も6時間ほどもある。本来このファイルは垂れ流しで聞くものなので、用途を間違えなければ問題はない。
しかし、途中まで聞いていて次に再生するときに頭から聞くのはつらいし、またお気に入りの曲からはじめるといったことも難しい。
そこで、インデックスを別途準備し、分割されてないにも関わらず分割されているような操作性を提供できないかと思った。

調べると、同様のことをFlacは既に実現しているらしい、フォーマットはCueSheetというファイルのようだ、独自フォーマットを作るのもやぶさかではないが、まずはCueSheetを調査し、良い部分を取り込む方向で作業をすすめることにした。
つまり、遠回りにはなるけど、まずはFlacCueSheet対応をしてみることにした。

結果、なんとかCueSheet対応ができた。
同様のアプリは既にPlayStoreにもあるため、新規性はないが容量の大きいファイルでもストレスなく再生できる点で他のアプリより優位性があるように思える。

同じ手法で、暫定的なフォーマットを作成し、MP3でも再生できることを確認した。

実用性が出てきた為、実装はこのあとさらに加速していく。
プレイリスト、フォルダ選択だけに限るが、曲の選択ができるように実装した。
再生中の画面としてビジュアライザーを実装した。
次はイコライザの実装にとりかかる。

そして、現在躓いている。

容量の大きい音楽ファイルの再生でイコライザーを設定すると、曲の頭出し時に”ジッ”というノイズがはいる。

これの除去がうまくいかない。

ここまで書いて、考えがまとまっていないことに気づいた。
まずは状況を分析することからはじめようとおもう。

・MediaPlayer1とMediaPlayer2
曲のギャップを減らすために、この2つに音楽ファイルを設定する、
ただし、次の曲が同じファイルの場合は2つ同じファイルを読むのは無駄なので、MediaPlayer2はPositionだけを保持した空のMediaPlayerになる。
これを実現するためにMediaPlayerをラップしている。

・AudioEffect
AudioEffectはMediaPlayerと1:1である必要はないため、MediaPlayer1とMediaPlayer2で共有している。つまりAudioSessionIDで一個つくっている。
これはサービス側の話。 イコライザーの設定画面でも一個もっている、こちらはAudioSessionIDをサービスから取得し生成している。
この際、イコライザー設定画面のイコライザーの優先順位を高くするためプライオリティーを高く設定している。

・Config
イコライザー設定画面からイコライザーの設定を変更したら、一旦Preferenceに値を保存する。
その後、Service側に変更を通知し、再読み込みを行う。


現在は上記のような実装になっている、ここまでくるのに、いくつかのTryErrorがあった、結局上記の手法でもノイズがはいるのだが。

現時点までの工夫として
・AudioEffectは何度も生成しないようにする。
・onPreparedのほかに、onSeekCompleteも実装し、曲が再生可能な状態になってからstartを行う。

以前、イコライザーのEnableをStartの直後にTrueにするようにしてみると、上手くいっていたことがあった、しかしこの場合、意図的に初期読み込み時はEnableをFalseしておく必要があるため状態管理に苦労した。動作が不安定になったのもこの処理が複雑になりすぎたためであるため、現在他の方法を模索している。

曲の読み込み時の一回目だけジッというのノイズがはいる、その後は曲の移動(Seek)ではノイズがはいらない、ロジックにどのような違いがあるのかもう一度見なおしてみる。










Tuesday, May 13, 2014

ようやく開発を始めました

JUST PLAYERの開発を始めました。
今の進捗とこれからの方針を報告します。

まず、いまの進捗ですが、少しづつですが開発は進んでいます。
4月中旬まで仕事で忙しく、こちらに手を付けることができませんでしたが、後半から手を付け、現在は半月ぐらい開発ができています。

とりあえず、報告できるぐらい開発が進んできましたのでここらへんでスクリーンショットも交えて紹介してみます。


Monday, January 6, 2014

新年のご挨拶

明けましておめでとうございます。
おかげさまでJUSTPLAYERも開発してから約3年が経過しました。
ということで以前から宣言してた通り、JUSTPLAYERは今年3度目の生まれ変わりを予定しています。



コンセプトとしては流行りのフラットデザインとナビゲーションドロワーを取り入れる予定です。
ただフラットデザインはシンプルが故にどれも似通ってしまうので個性がなくなりがちなんですよね。
特に音楽プレイヤーのように競争率の高いアプリでは、先駆者がフラットデザインを採用してしまうとどうしても模倣っぽくなってしまいます。
(音楽プレイヤーに必要な最低限の機能というのは絞れてしまうので…)

この辺りの課題についてはテーマやアニメーションを駆使することでグラフィカルなデザインまでカバーできる作りにしようと思います。

詳細は後日発表しますので、今しばらくお待ちください。