2016년 5월 12일 목요일

google glass - local music player 패치

이전에 적었던 글 에서 github 에 있는 local music player 를 소개 했었다. 한 2개월 정도 '통화중 정지 안됨', 'CPU 엄청 먹음' 이라는 치명적인 버그를 감수하고 local music 을 듣기 위해서 꾸역꾸역 실사용을 해 봤다. '덤으로 volume 조절도 안되는 문제도 있다.'

그동안은 그냥 저냥 음악만 들려 주면 그만이라는 생각으로 버텨왔었는데, smart home 과 car door 가 어느정도 정리되고 있어서 짬을 내어 급한 성능 문제라도 patch 해서 써야 겠다는 맘을 먹었다. 사실 2개월 전에는 안드로이드 코드를 볼줄도 몰랐었기 때문에 patch 를 하고 싶어도 할 수 가 없었던게 진실이다 ;;;;

하지만 최근에 startbucks wifi 자동연결 이라던지, arduino gps  관련된 google glass app 을 만지다 보니 은근히 android 에 대한 두려움이 적어졌다. 그래서 Service code 만 좀 손봐야지 하는 마음에 code review 를 해 봤다.

MainService 파일 중에 onStartCommand 부분을 보면
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    ...
    new AsyncTask<Void, Void, Boolean>() {
        @Override
        protected Boolean doInBackground(Void... params) {
            try {
                String selection = MediaStore.Audio.Media.IS_MUSIC + " != 0";
                String[] projection = {MediaStore.Audio.Media.DATA, MediaStore.Audio.Media._ID};
                Cursor c = getApplicationContext().getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                projection, selection, null, null);
                if (c != null) {
                    while (c.moveToNext()) {
                        String path = c.getString(0);
                        MusicItem mi = new MusicItem(path);
                        mi.setId(c.getLong(1));
                        mi.setAlbum(MusicUtil.getAlbum(path));
                        mi.setArtist(MusicUtil.getArtist(path));
                        mi.setTitle(MusicUtil.getSongTitle(path));
                        mi.setDuration(MusicUtil.getDuration(path));
                        songs.add(mi);
                    }

                }
                return true;
            } catch (Exception e) {
                return false;
            }
        }
        ...
}
빨간 부분이 문제로 보인다.
첫번째 null 은 system 전체를 뒤지면서 모든 음악 파일을 찾아 낸다는 의미이고, 두번째 while loop 은 첫번째에서 찾아낸 모든 파일을 songs 리스트에 더해서 playlist 를 만든다. 이것 때문에 초기 launching time 이 음악 파일수에 비례한 것은 당연한 얘기고, glass 하드웨어가 감당해 내기 버거운 상황이 발생한다.
android 의 media file 을 관리하는 정책이 어떤지는 잘 모르겠으나, system wide 한 media server 를 만드는 것도 아니고 나만 사용할 local media player 를 위한 것이니 최대한 가볍게 바꿔주면 될것 같았다.
그래서 2가지 patch 를 냈다.





1. /sdcard/Music 디렉토리만 바라보게 변경했다.
@@ -91,24 +96,31 @@ public class MainService extends Service { @Override protected Boolean doInBackground(Void... params) { try { String selection = MediaStore.Audio.Media.IS_MUSIC + " != 0"; - String[] projection = { MediaStore.Audio.Media.DATA, MediaStore.Audio.Media._ID}; - Cursor c = getApplicationContext().getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, - projection, selection, null, null); - if (c != null) { - while (c.moveToNext()) { - String path = c.getString(0); - MusicItem mi = new MusicItem(path); - mi.setId(c.getLong(1)); - mi.setAlbum(MusicUtil.getAlbum(path)); - mi.setArtist(MusicUtil.getArtist(path)); - mi.setTitle(MusicUtil.getSongTitle(path)); - mi.setDuration(MusicUtil.getDuration(path)); - songs.add(mi); - } - } + String _path = Environment.getExternalStorageDirectory().getPath(); + + String selection = MediaStore.Audio.Media.IS_MUSIC + " !=" + 0 + + " AND " + MediaStore.Audio.Media.DATA + " LIKE '" + _path + + "/Music/%'"; + String[] proj = { MediaStore.Audio.Media._ID, + MediaStore.Audio.Media.DATA, + MediaStore.Audio.Media.DISPLAY_NAME, + MediaStore.Audio.Media.SIZE }; + mCursor = getApplicationContext().getContentResolver().query( + MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, proj, selection, + null, null);
2. playlist 방식이 아닌, single file play 방식으로 변경했다.
@@ -379,9 +397,11 @@ public class MainService extends Service { public void nextTrack() { //If we are currently shuffling the songs, we choose our next song based on the appropriate list if (shuffled) { //Make sure we are in our limits of the shuffled list - if (songIndex + 1 < shuffledSongs.size()) { + if (songIndex + 1 < mCount) { try { if (handler != null) { handler.removeCallbacks(updateTask); songIndex++; mediaPlayer.stop(); mediaPlayer.reset(); - mediaPlayer.setDataSource(shuffledSongs.get(songIndex).getLocation()); + mediaPlayer.setDataSource(shuffledSongs.get(0).getLocation()); mediaPlayer.prepare(); mediaPlayer.start(); - render.setTextOfView(shuffledSongs.get(songIndex).getTitle(), shuffledSongs.get(songIndex).getArtist(), null); - Bitmap bm = cache.getBitmapFromMemCache(String.valueOf(shuffledSongs.get(songIndex).getLocation().hashCode())); + render.setTextOfView(shuffledSongs.get(0).getTitle(), shuffledSongs.get(0).getArtist(), null); + Bitmap bm = cache.getBitmapFromMemCache(String.valueOf(shuffledSongs.get(0).getLocation().hashCode())); if (bm == null) { - new LoadAlbumBitmap().execute(shuffledSongs.get(songIndex).getLocation()); + new LoadAlbumBitmap().execute(shuffledSongs.get(0).getLocation()); } else { render.setAlbumArtwork(bm); }
이렇게 변경 하므로써 launching time 현저히 줄었고, Sequential 한 nextTrack() 이 잘 동작한다. 물론 같은 방법으로 previousTrack() 과 shuffleMusic() 도 patch 해 주면 된다. 난 shuffle 을 사용할 일이 없어서 일단 그냥 둔다.

이정도만 손봐줘도 실사용에는 큰 무리가 없는 듯 한데, debugging 을 하다보니 좀 의아한 부분이 관찰된다. google glass 를 최초 부팅하고 한창 resource 를 loading 하는 중에 music play 를 하면 UI 가 날라가는 현상이 있다. 부팅 후 충분한 시간 (1분?) 이 지나서 사용하면 아무 문제가 없는데, 나중에 시간 나면 이 현상도 수정 해 봐야 겠다.

댓글 없음: