Merge pie-platform-release to aosp-master - DO NOT MERGE
Change-Id: Ic2b32f471401bdd6f3c151a4b157471d97826cf5
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 6adb4b3..c59c393 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -14,51 +14,27 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.music"
- android:versionCode="2"
- android:versionName="2.0">
+ xmlns:tools="http://schemas.android.com/tools">
<!-- Package Name -->
<original-package android:name="com.android.music"/>
<!-- SDK Versions -->
<uses-sdk android:minSdkVersion="19"
- android:targetSdkVersion="24"/>
+ android:targetSdkVersion="28"/>
<!-- Permissions -->
- <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
- <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
- <uses-permission android:name="android.permission.WAKE_LOCK"/>
- <uses-permission android:name="android.permission.INTERNET"/>
- <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
- <uses-permission android:name="android.permission.BROADCAST_STICKY"/>
<!-- App Declaration -->
<application
- android:icon="@drawable/app_music"
- android:label="@string/musicbrowserlabel"
- android:taskAffinity="android.task.music"
- android:allowTaskReparenting="true"
- android:usesCleartextTraffic="true">
-
- <!-- Meta Data -->
- <meta-data android:name="com.google.android.gms.car.application"
- android:resource="@xml/automotive_app_desc"/>
-
- <!-- Main Activity -->
- <activity android:name="com.android.music.MusicBrowserActivity"
- android:theme="@android:style/Theme.NoTitleBar"
- android:exported="true">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.DEFAULT"/>
- <category android:name="android.intent.category.LAUNCHER"/>
- <category android:name="android.intent.category.APP_MUSIC"/>
- </intent-filter>
- </activity>
+ android:allowBackup="true"
+ android:label="@string/app_name"
+ android:supportsRtl="true"
+ android:launchMode="singleTop">
<activity android:name="AudioPreview" android:theme="@android:style/Theme.Dialog"
android:taskAffinity=""
@@ -95,108 +71,9 @@
</intent-filter>
</activity>
- <activity android:name="com.android.music.MusicPicker"
- android:label="@string/music_picker_title" android:exported="true" >
- <!-- First way to invoke us: someone asks to get content of
- any of the audio types we support. -->
- <intent-filter>
- <action android:name="android.intent.action.GET_CONTENT" />
- <category android:name="android.intent.category.DEFAULT" />
- <category android:name="android.intent.category.OPENABLE" />
- <data android:mimeType="audio/*"/>
- <data android:mimeType="application/ogg"/>
- <data android:mimeType="application/x-ogg"/>
- </intent-filter>
- <!-- Second way to invoke us: someone asks to pick an item from
- some media Uri. -->
- <intent-filter>
- <action android:name="android.intent.action.PICK" />
- <category android:name="android.intent.category.DEFAULT" />
- <category android:name="android.intent.category.OPENABLE" />
- <data android:mimeType="vnd.android.cursor.dir/audio"/>
- </intent-filter>
- </activity>
-
- <!--
- This is the "current music playing" panel, which has special
- launch behavior. We clear its task affinity, so it will not
- be associated with the main media task and if launched
- from a notification will not bring the rest of the media app
- to the foreground. We make it singleTask so that when others
- launch it (such as media) we will launch in to our own task.
- We set clearTaskOnLaunch because the user
- can go to a playlist from this activity, so if they later return
- to it we want it back in its initial state. We exclude from
- recents since this is accessible through a notification when
- appropriate.
- -->
- <activity android:name="com.android.music.MediaPlaybackActivity"
- android:theme="@android:style/Theme.NoTitleBar"
- android:label="@string/mediaplaybacklabel"
- android:taskAffinity=""
- android:launchMode="singleTask"
- android:clearTaskOnLaunch="true"
- android:excludeFromRecents="true"
- android:exported="true">
- <intent-filter>
- <action android:name="android.intent.action.VIEW"/>
- <category android:name="android.intent.category.DEFAULT"/>
- <data android:scheme="content"/>
- <data android:host="media"/>
- <data android:mimeType="audio/*"/>
- <data android:mimeType="application/ogg"/>
- <data android:mimeType="application/x-ogg"/>
- <data android:mimeType="application/itunes"/>
- </intent-filter>
- <intent-filter>
- <action android:name="com.android.music.PLAYBACK_VIEWER"/>
- <category android:name="android.intent.category.DEFAULT"/>
- </intent-filter>
- </activity>
-
- <activity android:name="com.android.music.ArtistAlbumBrowserActivity"
- android:exported="false">
- <intent-filter>
- <action android:name="android.intent.action.PICK"/>
- <category android:name="android.intent.category.DEFAULT"/>
- <data android:mimeType="vnd.android.cursor.dir/artistalbum"/>
- </intent-filter>
- </activity>
-
- <activity android:name="com.android.music.AlbumBrowserActivity" android:exported="false">
- <intent-filter>
- <action android:name="android.intent.action.PICK"/>
- <category android:name="android.intent.category.DEFAULT"/>
- <data android:mimeType="vnd.android.cursor.dir/album"/>
- </intent-filter>
- </activity>
-
- <activity android:name="com.android.music.TrackBrowserActivity" android:exported="false">
- <intent-filter>
- <action android:name="android.intent.action.PICK"/>
- <category android:name="android.intent.category.DEFAULT"/>
- <data android:mimeType="vnd.android.cursor.dir/track"/>
- </intent-filter>
- </activity>
-
- <activity android:name="com.android.music.PlaylistBrowserActivity"
- android:label="@string/musicbrowserlabel"
- android:exported="true">
- <intent-filter>
- <action android:name="android.intent.action.PICK"/>
- <category android:name="android.intent.category.DEFAULT"/>
- <data android:mimeType="vnd.android.cursor.dir/playlist"/>
- </intent-filter>
- <intent-filter>
- <action android:name="android.intent.action.VIEW"/>
- <category android:name="android.intent.category.DEFAULT"/>
- <data android:mimeType="vnd.android.cursor.dir/playlist"/>
- </intent-filter>
- </activity>
-
<service android:name="com.android.music.MediaPlaybackService"
android:exported="true"
- android:label="Android Open Source Music Player">
+ android:label="Android Open Source Music Playback Service">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService" />
</intent-filter>
diff --git a/res/color/tab_indicator_text.xml b/res/color/tab_indicator_text.xml
deleted file mode 100644
index 62f522b..0000000
--- a/res/color/tab_indicator_text.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_selected="true" android:color="#ffffff"/>
- <item android:state_focused="true" android:color="#ffffff"/>
- <item android:color="#808080"/> <!-- not selected -->
-</selector>
diff --git a/res/drawable/appwidget_button_center.xml b/res/drawable/appwidget_button_center.xml
deleted file mode 100644
index 194b357..0000000
--- a/res/drawable/appwidget_button_center.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-
- <item android:state_pressed="true"
- android:drawable="@drawable/appwidget_inner_press_c" />
-
- <item android:state_focused="true" android:state_enabled="true"
- android:state_window_focused="true"
- android:drawable="@drawable/appwidget_inner_focus_c" />
-
- <item
- android:drawable="@android:color/transparent" />
-</selector>
diff --git a/res/drawable/appwidget_button_left.xml b/res/drawable/appwidget_button_left.xml
deleted file mode 100644
index cbbce86..0000000
--- a/res/drawable/appwidget_button_left.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-
- <item android:state_pressed="true"
- android:drawable="@drawable/appwidget_inner_press_l" />
-
- <item android:state_focused="true" android:state_enabled="true"
- android:state_window_focused="true"
- android:drawable="@drawable/appwidget_inner_focus_l" />
-
- <item
- android:drawable="@android:color/transparent" />
-</selector>
diff --git a/res/drawable/appwidget_button_right.xml b/res/drawable/appwidget_button_right.xml
deleted file mode 100644
index 9623f54..0000000
--- a/res/drawable/appwidget_button_right.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-
- <item android:state_pressed="true"
- android:drawable="@drawable/appwidget_inner_press_r" />
-
- <item android:state_focused="true" android:state_enabled="true"
- android:state_window_focused="true"
- android:drawable="@drawable/appwidget_inner_focus_r" />
-
- <item
- android:drawable="@android:color/transparent" />
-</selector>
diff --git a/res/drawable/buttonbarbackground.xml b/res/drawable/buttonbarbackground.xml
deleted file mode 100644
index 54f4181..0000000
--- a/res/drawable/buttonbarbackground.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:state_focused="true"
- android:drawable="@drawable/buttonbar_focused" />
- <item
- android:state_pressed="true"
- android:drawable="@drawable/buttonbar_pressed" />
- <item
- android:state_selected="true"
- android:drawable="@drawable/buttonbar_active" />
- <item
- android:state_selected="false"
- android:drawable="@drawable/buttonbar_inactive" />
-</selector>
diff --git a/res/drawable/ic_tab_albums.xml b/res/drawable/ic_tab_albums.xml
deleted file mode 100644
index 72957df..0000000
--- a/res/drawable/ic_tab_albums.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/ic_tab_albums_selected" />
- <item android:drawable="@drawable/ic_tab_albums_unselected" />
-</selector>
-
diff --git a/res/drawable/ic_tab_artists.xml b/res/drawable/ic_tab_artists.xml
deleted file mode 100644
index e79766a..0000000
--- a/res/drawable/ic_tab_artists.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/ic_tab_artists_selected" />
- <item android:drawable="@drawable/ic_tab_artists_unselected" />
-</selector>
-
diff --git a/res/drawable/ic_tab_playback.xml b/res/drawable/ic_tab_playback.xml
deleted file mode 100644
index bcb8312..0000000
--- a/res/drawable/ic_tab_playback.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/ic_tab_playback_selected" />
- <item android:drawable="@drawable/ic_tab_playback_unselected" />
-</selector>
-
diff --git a/res/drawable/ic_tab_playlists.xml b/res/drawable/ic_tab_playlists.xml
deleted file mode 100644
index 64e6353..0000000
--- a/res/drawable/ic_tab_playlists.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/ic_tab_playlists_selected" />
- <item android:drawable="@drawable/ic_tab_playlists_unselected" />
-</selector>
-
diff --git a/res/drawable/ic_tab_songs.xml b/res/drawable/ic_tab_songs.xml
deleted file mode 100644
index 7642017..0000000
--- a/res/drawable/ic_tab_songs.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/ic_tab_songs_selected" />
- <item android:drawable="@drawable/ic_tab_songs_unselected" />
-</selector>
-
diff --git a/res/drawable/list_selector.xml b/res/drawable/list_selector.xml
deleted file mode 100644
index d8afcb6..0000000
--- a/res/drawable/list_selector.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_selected="true"
- android:drawable="@android:color/transparent" />
- <item android:state_pressed="true" android:state_selected="false"
- android:drawable="@android:color/transparent" />
- <item android:state_selected="false"
- android:drawable="@color/expanding_child_background" />
-</selector>
diff --git a/res/drawable/list_selector_background.xml b/res/drawable/list_selector_background.xml
deleted file mode 100644
index 5f52682..0000000
--- a/res/drawable/list_selector_background.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-
- <item android:state_window_focused="false"
- android:drawable="@drawable/playlist_tile_normal" />
-
- <!-- Even though these two point to the same resource, have two states so the drawable will invalidate itself when coming out of pressed state. -->
- <item android:state_focused="true" android:state_enabled="false"
- android:state_pressed="true"
- android:drawable="@drawable/playlist_tile_normal" />
- <item android:state_focused="true" android:state_enabled="false"
- android:drawable="@drawable/playlist_tile_normal" />
-
- <item android:state_focused="true" android:state_pressed="true"
- android:drawable="@drawable/list_selector_background_transition" />
- <item android:state_focused="false" android:state_pressed="true"
- android:drawable="@drawable/list_selector_background_transition" />
-
- <item android:state_focused="true"
- android:drawable="@drawable/playlist_tile_selected" />
-
- <item android:state_focused="false"
- android:drawable="@drawable/playlist_tile_normal" />
-</selector>
diff --git a/res/drawable/list_selector_background_transition.xml b/res/drawable/list_selector_background_transition.xml
deleted file mode 100644
index d92b392..0000000
--- a/res/drawable/list_selector_background_transition.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<transition xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:drawable="@drawable/playlist_tile_pressed" />
- <item android:drawable="@drawable/playlist_tile_longpress" />
-</transition>
diff --git a/res/drawable/playlist_tile.xml b/res/drawable/playlist_tile.xml
deleted file mode 100644
index 5e85f36..0000000
--- a/res/drawable/playlist_tile.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-
- <item android:state_window_focused="false"
- android:drawable="@drawable/playlist_tile_normal" />
-
- <item android:state_focused="true" android:drawable="@color/transparent" />
- <item android:state_selected="true" android:drawable="@color/transparent" />
- <item android:state_pressed="true" android:drawable="@color/transparent" />
-
- <item android:state_focused="false" android:state_pressed="false"
- android:drawable="@drawable/playlist_tile_normal" />
-</selector>
diff --git a/res/layout-keysexposed/create_playlist.xml b/res/layout-keysexposed/create_playlist.xml
deleted file mode 100644
index 132210a..0000000
--- a/res/layout-keysexposed/create_playlist.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <TextView android:id="@+id/prompt"
- android:layout_width="match_parent" android:layout_height="wrap_content"
- android:text="@string/create_playlist_create_text_prompt"
- android:layout_marginTop="8dip"
- android:layout_marginBottom="8dip"
- android:layout_marginLeft="8dip"
- android:layout_marginRight="8dip">
- </TextView>
-
- <EditText android:id="@+id/playlist"
- android:layout_width="match_parent" android:layout_height="wrap_content"
- android:singleLine="true"
- android:inputType="textCapSentences"
- android:layout_marginBottom="8dip"
- android:layout_marginLeft="8dip"
- android:layout_marginRight="8dip">
- <requestFocus />
- </EditText>
-
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:padding="6dip"
- android:background="#ffffff" >
-
- <Button android:id="@+id/create"
- android:layout_width="120dip" android:layout_height="wrap_content"
- android:text="@string/create_playlist_create_text"
- android:layout_alignParentLeft="true" />
-
- <Button android:id="@+id/cancel"
- android:layout_width="120dip" android:layout_height="wrap_content"
- android:text="@string/cancel"
- android:layout_alignParentRight="true" />
-
- </RelativeLayout>
-
-</LinearLayout>
-
diff --git a/res/layout-keyshidden/create_playlist.xml b/res/layout-keyshidden/create_playlist.xml
deleted file mode 100644
index 04aefc9..0000000
--- a/res/layout-keyshidden/create_playlist.xml
+++ /dev/null
@@ -1,71 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="8dip"
- android:layout_marginTop="8dip"
- android:layout_marginLeft="8dip"
- android:layout_marginRight="8dip">
-
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_slide_keyboard"/>
-
- <TextView android:id="@+id/prompt"
- android:layout_width="match_parent" android:layout_height="wrap_content"
- android:text="@string/create_playlist_create_text_prompt"
- android:layout_marginLeft="8dip">
- </TextView>
- </LinearLayout>
-
- <EditText android:id="@+id/playlist"
- android:layout_width="match_parent" android:layout_height="wrap_content"
- android:singleLine="true"
- android:inputType="textCapSentences"
- android:visibility="gone"
- android:layout_marginBottom="8dip">
- <requestFocus />
- </EditText>
-
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:padding="6dip"
- android:background="#ffffff" >
-
- <Button android:id="@+id/create"
- android:layout_width="120dip" android:layout_height="wrap_content"
- android:text="@string/create_playlist_create_text"
- android:layout_alignParentLeft="true" />
-
- <Button android:id="@+id/cancel"
- android:layout_width="120dip" android:layout_height="wrap_content"
- android:text="@string/cancel"
- android:layout_alignParentRight="true" />
-
- </RelativeLayout>
-
-</LinearLayout>
-
diff --git a/res/layout-land/audio_player.xml b/res/layout-land/audio_player.xml
deleted file mode 100644
index 982c2cc..0000000
--- a/res/layout-land/audio_player.xml
+++ /dev/null
@@ -1,159 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
-
- <!-- This is the LinearLayout that contains the album art, function buttons and album/artist/track info -->
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1"
- android:orientation="horizontal">
-
- <ImageView
- android:id="@+id/album"
- android:background="@drawable/album_border_large"
- android:layout_width="183dip"
- android:layout_height="183dip"
- android:layout_marginLeft="12dip"
- android:layout_marginRight="15dip"
- android:layout_marginTop="12dip" />
-
- <!-- This is the LinearLayout that contains function buttons and album/artist/track info -->
- <LinearLayout
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:orientation="vertical">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:paddingTop="20dip" >
-
- <ImageButton android:id="@+id/curplaylist"
- android:src="@drawable/ic_mp_current_playlist_btn"
- android:layout_width="82dip"
- android:layout_height="45dip"
- android:layout_marginRight="8dip"
- android:nextFocusLeft="@id/curplaylist" />
-
- <ImageButton android:id="@+id/shuffle"
- android:layout_width="82dip"
- android:layout_height="45dip"
- android:layout_marginRight="8dip" />
-
- <ImageButton android:id="@+id/repeat"
- android:layout_width="82dip"
- android:layout_height="45dip" />
-
- </LinearLayout>
-
- <!-- This is the LinearLayout that contains album/artist/track info -->
- <LinearLayout android:id="@+id/trackinfo"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:baselineAligned="false"
- android:paddingTop="8dip"
- android:paddingBottom="2dip">
-
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="4dip"
- android:src="@drawable/ic_mp_artist_playback" />
-
- <TextView android:id="@+id/artistname"
- android:textSize="18sp"
- android:singleLine="true"
- android:ellipsize="end"
- android:textStyle="bold"
- android:layout_gravity="center_vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:baselineAligned="false"
- android:paddingTop="8dip"
- android:paddingBottom="2dip">
-
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="4dip"
- android:src="@drawable/ic_mp_album_playback" />
-
- <TextView android:id="@+id/albumname"
- android:textSize="14sp"
- android:singleLine="true"
- android:ellipsize="end"
- android:textStyle="bold"
- android:layout_gravity="center_vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:baselineAligned="false"
- android:paddingTop="4dip"
- android:paddingBottom="2dip">
-
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="4dip"
- android:src="@drawable/ic_mp_song_playback" />
-
- <TextView android:id="@+id/trackname"
- android:textSize="14sp"
- android:singleLine="true"
- android:ellipsize="end"
- android:textStyle="bold"
- android:layout_gravity="center_vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
- </LinearLayout>
-
- </LinearLayout>
-
- </LinearLayout>
-
- </LinearLayout>
-
- <include layout="@layout/audio_player_common" />
-
-</LinearLayout>
diff --git a/res/layout-land/buttonbar.xml b/res/layout-land/buttonbar.xml
deleted file mode 100644
index f27907d..0000000
--- a/res/layout-land/buttonbar.xml
+++ /dev/null
@@ -1,111 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<TabWidget xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/buttonbar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" >
-
- <TextView
- android:id="@+id/artisttab"
- android:focusable="true"
- android:background="@drawable/buttonbarbackground"
- android:drawableTop="@drawable/ic_tab_artists"
- android:text="@string/browse_menu"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/tab_indicator_text"
- android:paddingTop="7dip"
- android:paddingBottom="2dip"
- android:gravity="center"
- android:layout_weight="1"
- android:layout_marginLeft="-3dip"
- android:layout_marginRight="-3dip"
- android:layout_width="match_parent"
- android:layout_height="64dip" />
-
- <TextView
- android:id="@+id/albumtab"
- android:focusable="true"
- android:background="@drawable/buttonbarbackground"
- android:drawableTop="@drawable/ic_tab_albums"
- android:text="@string/albums_menu"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/tab_indicator_text"
- android:paddingTop="7dip"
- android:paddingBottom="2dip"
- android:gravity="center"
- android:layout_weight="1"
- android:layout_marginLeft="-3dip"
- android:layout_marginRight="-3dip"
- android:layout_width="match_parent"
- android:layout_height="64dip" />
-
- <TextView
- android:id="@+id/songtab"
- android:focusable="true"
- android:background="@drawable/buttonbarbackground"
- android:drawableTop="@drawable/ic_tab_songs"
- android:text="@string/tracks_menu"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/tab_indicator_text"
- android:paddingTop="7dip"
- android:paddingBottom="2dip"
- android:gravity="center"
- android:layout_weight="1"
- android:layout_marginLeft="-3dip"
- android:layout_marginRight="-3dip"
- android:layout_width="match_parent"
- android:layout_height="64dip" />
-
- <TextView
- android:id="@+id/playlisttab"
- android:focusable="true"
- android:background="@drawable/buttonbarbackground"
- android:drawableTop="@drawable/ic_tab_playlists"
- android:text="@string/playlists_menu"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/tab_indicator_text"
- android:paddingTop="7dip"
- android:paddingBottom="2dip"
- android:gravity="center"
- android:layout_weight="1"
- android:layout_marginLeft="-3dip"
- android:layout_marginRight="-3dip"
- android:layout_width="match_parent"
- android:layout_height="64dip" />
-
- <TextView
- android:id="@+id/nowplayingtab"
- android:focusable="false"
- android:background="@drawable/buttonbarbackground"
- android:drawableTop="@drawable/ic_tab_playback"
- android:text="@string/nowplaying_title"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/tab_indicator_text"
- android:paddingTop="7dip"
- android:paddingBottom="2dip"
- android:gravity="center"
- android:layout_weight="1"
- android:layout_marginLeft="3dip"
- android:layout_marginRight="-3dip"
- android:layout_width="match_parent"
- android:layout_height="64dip" />
-
-</TabWidget>
-
diff --git a/res/layout-land/media_picker_activity.xml b/res/layout-land/media_picker_activity.xml
deleted file mode 100644
index 77a9919..0000000
--- a/res/layout-land/media_picker_activity.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:gravity="center_vertical" >
-
- <include layout="@layout/sd_error" />
-
- <include layout="@layout/buttonbar" />
-
- <com.android.music.TouchInterceptor
- android:id="@android:id/list"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:textSize="18sp"
- android:drawSelectorOnTop="false"
- android:fastScrollEnabled="true" />
-
-</LinearLayout>
diff --git a/res/layout-land/media_picker_activity_expanding.xml b/res/layout-land/media_picker_activity_expanding.xml
deleted file mode 100644
index 9386eb8..0000000
--- a/res/layout-land/media_picker_activity_expanding.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:gravity="center_vertical" >
-
- <include layout="@layout/sd_error" />
-
- <include layout="@layout/buttonbar" />
-
- <ExpandableListView
- android:id="@android:id/list"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:textSize="18sp"
- android:drawSelectorOnTop="false"
- android:fastScrollEnabled="true"
- android:indicatorLeft="8dip"
- android:indicatorRight="52dip" />
-
-</LinearLayout>
diff --git a/res/layout-port-finger-854x480/audio_player.xml b/res/layout-port-finger-854x480/audio_player.xml
deleted file mode 100644
index 95f857c..0000000
--- a/res/layout-port-finger-854x480/audio_player.xml
+++ /dev/null
@@ -1,137 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <ImageView
- android:id="@+id/album"
- android:background="@drawable/album_border_large"
- android:layout_width="270dip"
- android:layout_height="270dip"
- android:layout_gravity="center_horizontal"
- android:layout_marginTop="0dip" />
-
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="0dip"
- android:layout_weight="1"
- android:orientation="horizontal"
- android:layout_gravity="center_horizontal">
-
- <ImageButton android:id="@+id/curplaylist"
- android:src="@drawable/ic_mp_current_playlist_btn"
- android:layout_width="85dip"
- android:layout_height="54dip" />
-
- <ImageButton android:id="@+id/shuffle"
- android:layout_width="85dip"
- android:layout_height="54dip"
- android:layout_marginLeft="19dip" />
-
- <ImageButton android:id="@+id/repeat"
- android:layout_width="85dip"
- android:layout_height="54dip"
- android:layout_marginLeft="19dip" />
-
- </LinearLayout>
-
- <LinearLayout android:id="@+id/trackinfo"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:baselineAligned="false"
- android:paddingLeft="11dip"
- android:paddingTop="2dip"
- android:paddingBottom="4dip">
-
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="4dip"
- android:src="@drawable/ic_mp_artist_playback" />
-
- <TextView android:id="@+id/artistname"
- android:textSize="18sp"
- android:singleLine="true"
- android:ellipsize="end"
- android:textStyle="bold"
- android:layout_gravity="center_vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:baselineAligned="false"
- android:paddingLeft="11dip"
- android:paddingTop="4dip"
- android:paddingBottom="8dip">
-
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="4dip"
- android:src="@drawable/ic_mp_album_playback" />
-
- <TextView android:id="@+id/albumname"
- android:textSize="14sp"
- android:singleLine="true"
- android:ellipsize="end"
- android:layout_gravity="center_vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:baselineAligned="false"
- android:paddingLeft="11dip"
- android:paddingTop="0dip"
- android:paddingBottom="8dip">
-
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="4dip"
- android:src="@drawable/ic_mp_song_playback" />
-
- <TextView android:id="@+id/trackname"
- android:textSize="14sp"
- android:singleLine="true"
- android:ellipsize="end"
- android:layout_gravity="center_vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
- </LinearLayout>
- </LinearLayout>
-
- <include layout="@layout/audio_player_common" />
-
-</LinearLayout>
diff --git a/res/layout/album_appwidget.xml b/res/layout/album_appwidget.xml
deleted file mode 100644
index b5d0908..0000000
--- a/res/layout/album_appwidget.xml
+++ /dev/null
@@ -1,95 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal"
- android:background="@drawable/appwidget_bg">
-
- <LinearLayout
- android:id="@+id/album_appwidget"
- android:layout_width="0dip"
- android:layout_weight="3"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:gravity="center_vertical"
- android:clickable="true"
- android:focusable="true"
- android:background="@drawable/appwidget_button_left"
- android:paddingLeft="18dip"
- android:paddingRight="8dip"
- >
-
- <TextView
- android:id="@+id/title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:textColor="@color/appwidget_text"
- android:textStyle="bold"
- android:textSize="18sp"
- android:singleLine="true"
- android:fadingEdge="horizontal"
- android:fadingEdgeLength="10dip"
- android:ellipsize="none"
- />
-
- <TextView
- android:id="@+id/artist"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:textColor="@color/appwidget_text"
- android:textSize="14sp"
- android:singleLine="true"
- android:fadingEdge="horizontal"
- android:fadingEdgeLength="10dip"
- android:ellipsize="none"
- />
- </LinearLayout>
-
- <ImageView
- android:layout_width="1dip"
- android:layout_height="match_parent"
- android:background="@drawable/appwidget_divider"
- />
-
- <ImageButton
- android:id="@+id/control_play"
- android:layout_width="0dip"
- android:layout_weight="1"
- android:layout_height="match_parent"
- android:src="@drawable/ic_appwidget_music_play"
- android:background="@drawable/appwidget_button_center"
- android:scaleType="center"
- />
-
- <ImageView
- android:layout_width="1dip"
- android:layout_height="match_parent"
- android:background="@drawable/appwidget_divider"
- />
-
- <ImageButton
- android:id="@+id/control_next"
- android:layout_width="0dip"
- android:layout_weight="1"
- android:layout_height="match_parent"
- android:src="@drawable/ic_appwidget_music_next"
- android:background="@drawable/appwidget_button_right"
- android:scaleType="center"
- />
-
-</LinearLayout>
diff --git a/res/layout/audio_player.xml b/res/layout/audio_player.xml
deleted file mode 100644
index a8a1921..0000000
--- a/res/layout/audio_player.xml
+++ /dev/null
@@ -1,148 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1"
- android:orientation="horizontal"
- android:gravity="center">
-
- <ImageView
- android:id="@+id/album"
- android:background="@drawable/album_border_large"
- android:layout_width="220dip"
- android:layout_height="220dip"
- android:layout_marginLeft="4dip"
- android:layout_marginRight="2dip"
- android:layout_marginTop="8dip" />
-
- <LinearLayout
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:orientation="vertical"
- android:gravity="center_horizontal">
-
- <ImageButton android:id="@+id/curplaylist"
- android:src="@drawable/ic_mp_current_playlist_btn"
- android:layout_width="85dip"
- android:layout_height="54dip"
- android:layout_marginTop="14dip" />
-
- <ImageButton android:id="@+id/shuffle"
- android:layout_width="85dip"
- android:layout_height="54dip"
- android:layout_marginTop="20dip" />
-
- <ImageButton android:id="@+id/repeat"
- android:layout_width="85dip"
- android:layout_height="54dip"
- android:layout_marginTop="20dip" />
-
- </LinearLayout>
-
- </LinearLayout>
-
- <LinearLayout android:id="@+id/trackinfo"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:baselineAligned="false"
- android:paddingLeft="11dip"
- android:paddingTop="4dip"
- android:paddingBottom="8dip">
-
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="4dip"
- android:src="@drawable/ic_mp_artist_playback" />
-
- <TextView android:id="@+id/artistname"
- android:textSize="18sp"
- android:singleLine="true"
- android:ellipsize="end"
- android:textStyle="bold"
- android:layout_gravity="center_vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:baselineAligned="false"
- android:paddingLeft="11dip"
- android:paddingTop="4dip"
- android:paddingBottom="8dip">
-
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="4dip"
- android:src="@drawable/ic_mp_album_playback" />
-
- <TextView android:id="@+id/albumname"
- android:textSize="14sp"
- android:singleLine="true"
- android:ellipsize="end"
- android:layout_gravity="center_vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:baselineAligned="false"
- android:paddingLeft="11dip"
- android:paddingTop="0dip"
- android:paddingBottom="8dip">
-
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="4dip"
- android:src="@drawable/ic_mp_song_playback" />
-
- <TextView android:id="@+id/trackname"
- android:textSize="14sp"
- android:singleLine="true"
- android:ellipsize="end"
- android:layout_gravity="center_vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
- </LinearLayout>
- </LinearLayout>
-
- <include layout="@layout/audio_player_common" />
-
-</LinearLayout>
diff --git a/res/layout/audio_player_common.xml b/res/layout/audio_player_common.xml
deleted file mode 100644
index 4a7ceca..0000000
--- a/res/layout/audio_player_common.xml
+++ /dev/null
@@ -1,89 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
-
- <View
- android:layout_width="match_parent"
- android:layout_height="1px"
- android:background="#ffffffff" />
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="#ff5a5a5a"
- android:paddingTop="1dip"
- android:paddingBottom="4dip"
- android:orientation="horizontal">
-
- <TextView android:id="@+id/currenttime"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="14sp"
- android:textStyle="bold"
- android:shadowColor="#ff000000"
- android:shadowDx="0"
- android:shadowDy="0"
- android:shadowRadius="3"
- android:layout_gravity="bottom"
- android:layout_weight="1"
- android:layout_width="0dip"
- android:paddingLeft="5dip"
- android:layout_height="wrap_content" />
-
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="bottom"
- android:layout_marginTop="1dip"
- android:layout_marginBottom="2dip"
- android:gravity="center">
-
- <com.android.music.RepeatingImageButton android:id="@+id/prev" style="@android:style/MediaButton.Previous" />
-
- <ImageButton android:id="@+id/pause" style="@android:style/MediaButton.Play" />
-
- <com.android.music.RepeatingImageButton android:id="@+id/next" style="@android:style/MediaButton.Next" />
-
- </LinearLayout>
-
- <TextView android:id="@+id/totaltime"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="14sp"
- android:textStyle="bold"
- android:shadowColor="#ff000000"
- android:shadowDx="0"
- android:shadowDy="0"
- android:shadowRadius="3"
- android:gravity="right"
- android:paddingRight="5dip"
- android:layout_gravity="bottom"
- android:layout_weight="1"
- android:layout_width="0dip"
- android:layout_height="wrap_content" />
-
- </LinearLayout>
-
- <SeekBar android:id="@android:id/progress"
- android:background="#ff5a5a5a"
- style="?android:attr/progressBarStyleHorizontal"
- android:layout_width="match_parent"
- android:layout_height="36dip"
- android:paddingLeft="8dip"
- android:paddingRight="8dip"
- android:paddingBottom="4dip" />
-
-</merge>
diff --git a/res/layout/buttonbar.xml b/res/layout/buttonbar.xml
deleted file mode 100644
index 8c4e05a..0000000
--- a/res/layout/buttonbar.xml
+++ /dev/null
@@ -1,94 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<TabWidget xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/buttonbar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" >
-
- <TextView
- android:id="@+id/artisttab"
- android:focusable="true"
- android:background="@drawable/buttonbarbackground"
- android:drawableTop="@drawable/ic_tab_artists"
- android:text="@string/browse_menu"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/tab_indicator_text"
- android:paddingTop="7dip"
- android:paddingBottom="2dip"
- android:gravity="center"
- android:layout_weight="1"
- android:layout_marginLeft="-3dip"
- android:layout_marginRight="-3dip"
- android:layout_width="match_parent"
- android:layout_height="64dip" />
-
- <TextView
- android:id="@+id/albumtab"
- android:focusable="true"
- android:background="@drawable/buttonbarbackground"
- android:drawableTop="@drawable/ic_tab_albums"
- android:text="@string/albums_menu"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/tab_indicator_text"
- android:paddingTop="7dip"
- android:paddingBottom="2dip"
- android:gravity="center"
- android:layout_weight="1"
- android:layout_marginLeft="-3dip"
- android:layout_marginRight="-3dip"
- android:layout_width="match_parent"
- android:layout_height="64dip" />
-
- <TextView
- android:id="@+id/songtab"
- android:focusable="true"
- android:background="@drawable/buttonbarbackground"
- android:drawableTop="@drawable/ic_tab_songs"
- android:text="@string/tracks_menu"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/tab_indicator_text"
- android:paddingTop="7dip"
- android:paddingBottom="2dip"
- android:gravity="center"
- android:layout_weight="1"
- android:layout_marginLeft="-3dip"
- android:layout_marginRight="-3dip"
- android:layout_width="match_parent"
- android:layout_height="64dip" />
-
- <TextView
- android:id="@+id/playlisttab"
- android:focusable="true"
- android:background="@drawable/buttonbarbackground"
- android:drawableTop="@drawable/ic_tab_playlists"
- android:text="@string/playlists_menu"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/tab_indicator_text"
- android:paddingTop="7dip"
- android:paddingBottom="2dip"
- android:gravity="center"
- android:layout_weight="1"
- android:layout_marginLeft="-3dip"
- android:layout_marginRight="-3dip"
- android:layout_width="match_parent"
- android:layout_height="64dip" />
-
-</TabWidget>
-
diff --git a/res/layout/confirm_delete.xml b/res/layout/confirm_delete.xml
deleted file mode 100644
index 508fbdb..0000000
--- a/res/layout/confirm_delete.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <TextView android:id="@+id/prompt"
- android:layout_width="match_parent" android:layout_height="wrap_content"
- android:layout_marginLeft="8dip"
- android:layout_marginTop="8dip"
- android:layout_marginBottom="8dip"
- android:drawableLeft="@android:drawable/ic_dialog_alert"
- android:drawablePadding="8dip">
- </TextView>
-
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:padding="6dip"
- android:background="#ffffff" >
-
- <Button android:id="@+id/delete"
- android:layout_width="120dip" android:layout_height="wrap_content"
- android:text="@string/delete_confirm_button_text"
- android:layout_gravity="center_horizontal"
- android:layout_alignParentLeft="true" />
-
- <Button android:id="@+id/cancel"
- android:layout_width="120dip" android:layout_height="wrap_content"
- android:text="@string/cancel"
- android:layout_alignParentRight="true" />
-
- </RelativeLayout>
-
-</LinearLayout>
-
diff --git a/res/layout/edit_track_list_item.xml b/res/layout/edit_track_list_item.xml
deleted file mode 100644
index e8307bb..0000000
--- a/res/layout/edit_track_list_item.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="66dip"
- android:gravity="bottom"
- android:orientation="vertical"
- android:baselineAligned="false">
-
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="66dip"
- android:gravity="center_vertical"
- android:ignoreGravity="@+id/icon"
- android:background="@drawable/playlist_tile"
- android:paddingLeft="47dip"
- >
-
- <include layout="@layout/track_list_item_common" />
-
- </RelativeLayout>
-
-</LinearLayout>
diff --git a/res/layout/media_picker_activity.xml b/res/layout/media_picker_activity.xml
deleted file mode 100644
index af3d992..0000000
--- a/res/layout/media_picker_activity.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:gravity="center_vertical" >
-
- <include layout="@layout/sd_error" />
-
- <include layout="@layout/buttonbar" />
-
- <com.android.music.TouchInterceptor
- android:id="@android:id/list"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:textSize="18sp"
- android:drawSelectorOnTop="false"
- android:fastScrollEnabled="true" />
-
- <include layout="@layout/nowplaying" />
-
-</LinearLayout>
diff --git a/res/layout/media_picker_activity_expanding.xml b/res/layout/media_picker_activity_expanding.xml
deleted file mode 100644
index 4811f64..0000000
--- a/res/layout/media_picker_activity_expanding.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:gravity="center_vertical" >
-
- <include layout="@layout/sd_error" />
-
- <include layout="@layout/buttonbar" />
-
- <ExpandableListView
- android:id="@android:id/list"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:textSize="18sp"
- android:drawSelectorOnTop="false"
- android:fastScrollEnabled="true"
- android:indicatorLeft="8dip"
- android:indicatorRight="52dip" />
-
- <include layout="@layout/nowplaying" />
-
-</LinearLayout>
diff --git a/res/layout/music_picker.xml b/res/layout/music_picker.xml
deleted file mode 100644
index 0f97fcf..0000000
--- a/res/layout/music_picker.xml
+++ /dev/null
@@ -1,89 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2008 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <FrameLayout
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1">
-
- <LinearLayout android:id="@+id/progressContainer"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center">
-
- <ProgressBar android:id="@+android:id/progress"
- style="?android:attr/progressBarStyleLarge"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- <TextView android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:text="@string/loading"
- android:paddingTop="4dip"
- android:singleLine="true" />
-
- </LinearLayout>
-
- <FrameLayout android:id="@+id/listContainer"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <ListView android:id="@android:id/list"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:drawSelectorOnTop="false"
- android:fastScrollEnabled="true" />
- <TextView android:id="@android:id/empty"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center"
- android:text="@string/no_tracks_title"
- android:textAppearance="?android:attr/textAppearanceLarge" />
- </FrameLayout>
-
- </FrameLayout>
-
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="?android:attr/listPreferredItemHeight"
- android:layout_marginTop="1dip"
- android:background="@android:drawable/bottom_bar">
- <Button android:id="@+id/okayButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerVertical="true"
- android:layout_alignParentLeft="true"
- android:text="@android:string/ok"
- android:minWidth="120dip"
- android:minHeight="48dip" />
- <Button android:id="@+id/cancelButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerVertical="true"
- android:layout_alignParentRight="true"
- android:text="@android:string/cancel"
- android:minWidth="120dip"
- android:minHeight="48dip" />
- </RelativeLayout>
-
-</LinearLayout>
diff --git a/res/layout/music_picker_item.xml b/res/layout/music_picker_item.xml
deleted file mode 100644
index cf0f637..0000000
--- a/res/layout/music_picker_item.xml
+++ /dev/null
@@ -1,79 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2007, Google Inc.
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<com.android.music.utils.CheckableRelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="64dip"
- android:gravity="center_vertical"
- android:ignoreGravity="@+id/radio">
-
- <RadioButton
- android:id="@+id/radio"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:layout_alignParentLeft="true"
- android:layout_centerVertical="true"
- android:layout_marginLeft="4dip"
- android:focusable="false"
- android:clickable="false" />
-
- <TextView android:id="@+id/duration"
- android:layout_alignParentRight="true"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignBaseline="@+id/line1"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="#ffe0d090"
- android:paddingLeft="4dip"
- android:paddingRight="5dip"
- android:singleLine="true" />
-
- <TextView android:id="@+id/line1"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_width="wrap_content"
- android:paddingLeft="4dip"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_alignWithParentIfMissing="true"
- android:layout_toRightOf="@id/radio"
- android:layout_toLeftOf="@id/duration"
- android:ellipsize="end"
- android:singleLine="true" />
-
- <TextView android:id="@+id/line2" android:visibility="visible"
- android:maxLines="2"
- android:ellipsize="end"
- android:paddingLeft="4dip"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:layout_below="@id/line1"
- android:layout_alignWithParentIfMissing="true"
- android:layout_toRightOf="@id/radio"
- android:layout_toLeftOf="@id/duration"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
-
- <ImageView android:id="@+id/play_indicator"
- android:layout_alignParentRight="true"
- android:layout_alignBottom="@id/line2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="6dip" />
-
-</com.android.music.utils.CheckableRelativeLayout>
diff --git a/res/layout/nowplaying.xml b/res/layout/nowplaying.xml
deleted file mode 100644
index 15ee78b..0000000
--- a/res/layout/nowplaying.xml
+++ /dev/null
@@ -1,71 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/nowplaying"
- android:layout_width="match_parent"
- android:layout_height="64dip"
- android:focusable="true"
- android:visibility="gone"
- android:background="@drawable/music_bottom_playback_bg"
- android:orientation="vertical"
- android:paddingTop="3dip"
- android:paddingBottom="2dip">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal">
-
- <LinearLayout
- android:layout_width="0dip"
- android:layout_weight="1"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:orientation="vertical">
-
- <TextView
- android:id="@+id/title"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:singleLine="true"
- android:ellipsize="end"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- />
- <TextView
- android:id="@+id/artist"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:singleLine="true"
- android:ellipsize="end"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- />
- </LinearLayout>
-
- <ImageView android:id="@+id/icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:layout_marginLeft="16dip"
- android:background="@drawable/indicator_ic_mp_playing_large"
- />
-
- </LinearLayout>
-</LinearLayout>
-
diff --git a/res/layout/query_activity.xml b/res/layout/query_activity.xml
deleted file mode 100644
index 7575364..0000000
--- a/res/layout/query_activity.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:gravity="center_vertical" >
-
- <include layout="@layout/sd_error" />
-
- <ListView android:id="@android:id/list"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:drawSelectorOnTop="false">
- </ListView>
-</LinearLayout>
-
diff --git a/res/layout/scanning.xml b/res/layout/scanning.xml
deleted file mode 100644
index c4aa9ad..0000000
--- a/res/layout/scanning.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:padding="12dip">
-
- <ProgressBar android:id="@+id/spinner"
- style="?android:attr/progressBarStyleLarge"
- android:layout_gravity="center"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
-
- <TextView android:id="@+id/message"
- android:layout_gravity="center"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:text="@string/scanning">
- </TextView>
-
-</LinearLayout>
-
diff --git a/res/layout/scanning_nosdcard.xml b/res/layout/scanning_nosdcard.xml
deleted file mode 100644
index bb09fb8..0000000
--- a/res/layout/scanning_nosdcard.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:padding="12dip">
-
- <ProgressBar android:id="@+id/spinner"
- style="?android:attr/progressBarStyleLarge"
- android:layout_gravity="center"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
-
- <TextView android:id="@+id/message"
- android:layout_gravity="center"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:text="@string/scanning_nosdcard">
- </TextView>
-
-</LinearLayout>
-
diff --git a/res/layout/sd_error.xml b/res/layout/sd_error.xml
deleted file mode 100644
index 8a40305..0000000
--- a/res/layout/sd_error.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
- <ImageView
- android:id="@+id/sd_icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:background="@drawable/ic_mp_sd_card"
- android:visibility="gone" />
-
- <TextView
- android:id="@+id/sd_message"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:padding="8dip"
- android:text="@string/sdcard_missing_message"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:visibility="gone" />
-
-</merge>
diff --git a/res/layout/statusbar.xml b/res/layout/statusbar.xml
deleted file mode 100644
index c8d3fb6..0000000
--- a/res/layout/statusbar.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal">
-
- <ImageView android:id="@+id/icon"
- android:padding="4dip"
- android:gravity="center"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content">
- </ImageView>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
-
- <TextView android:id="@+id/trackname"
- style="@android:style/TextAppearance.StatusBar.EventContent.Title"
- android:focusable="true"
- android:ellipsize="marquee"
- android:singleLine="true"
- android:layout_gravity="left"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
-
- <TextView android:id="@+id/artistalbum"
- style="@android:style/TextAppearance.StatusBar.EventContent"
- android:layout_gravity="left"
- android:maxLines="2"
- android:scrollHorizontally="true"
- android:ellipsize="end"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- </LinearLayout>
-</LinearLayout>
diff --git a/res/layout/track_list_item.xml b/res/layout/track_list_item.xml
deleted file mode 100644
index 9b1d703..0000000
--- a/res/layout/track_list_item.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="64dip"
- android:gravity="center_vertical"
- android:ignoreGravity="@+id/icon">
-
- <include layout="@layout/track_list_item_common" />
-
-</RelativeLayout>
diff --git a/res/layout/track_list_item_child.xml b/res/layout/track_list_item_child.xml
deleted file mode 100644
index 9398182..0000000
--- a/res/layout/track_list_item_child.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="64dip"
- android:background="@drawable/list_selector"
- android:gravity="center_vertical"
- android:ignoreGravity="@+id/icon">
-
- <include layout="@layout/track_list_item_common" />
-
-</RelativeLayout>
diff --git a/res/layout/track_list_item_common.xml b/res/layout/track_list_item_common.xml
deleted file mode 100644
index e91bc29..0000000
--- a/res/layout/track_list_item_common.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
-
- <!-- icon is used for albumart, the grabber in edit playlist mode, and the playlist icon in the list of playlists -->
- <ImageView android:id="@+id/icon"
- android:layout_alignParentLeft="true"
- android:layout_alignParentTop="true"
- android:layout_alignParentBottom="true"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
-
- <TextView android:id="@+id/duration"
- android:textSize="12sp"
- android:textColor="?android:attr/textColorTertiary"
- android:textStyle="bold"
- android:paddingLeft="4dip"
- android:paddingRight="11dip"
- android:layout_alignParentRight="true"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignBaseline="@+id/line1"
- android:singleLine="true" />
-
- <!-- The height is set to half the height of the parent, which is 64 dip -->
- <TextView android:id="@+id/line1"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_width="wrap_content"
- android:paddingLeft="9dip"
- android:layout_height="wrap_content"
- android:layout_alignWithParentIfMissing="true"
- android:layout_toRightOf="@id/icon"
- android:layout_toLeftOf="@id/duration"
- android:ellipsize="marquee"
- android:singleLine="true" />
-
- <!-- The height is set to half the height of the parent, which is 64 dip -->
- <TextView android:id="@+id/line2" android:visibility="visible"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:singleLine="true"
- android:ellipsize="end"
- android:paddingLeft="9dip"
- android:scrollHorizontally="true"
- android:layout_below="@id/line1"
- android:layout_alignWithParentIfMissing="true"
- android:layout_toRightOf="@id/icon"
- android:layout_toLeftOf="@id/duration"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
-
- <ImageView android:id="@+id/play_indicator"
- android:layout_alignParentRight="true"
- android:layout_below="@id/duration"
- android:layout_marginTop="10dip"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="12dip" />
-
-</merge>
diff --git a/res/layout/track_list_item_group.xml b/res/layout/track_list_item_group.xml
deleted file mode 100644
index 79a2de1..0000000
--- a/res/layout/track_list_item_group.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="64dip"
- android:gravity="center_vertical"
- android:ignoreGravity="@+id/icon"
- android:paddingLeft="47dip">
-
- <include layout="@layout/track_list_item_common" />
-
-</RelativeLayout>
diff --git a/res/layout/weekpicker.xml b/res/layout/weekpicker.xml
deleted file mode 100644
index 01869ef..0000000
--- a/res/layout/weekpicker.xml
+++ /dev/null
@@ -1,68 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- Layout of time picker-->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <TextView
- android:text="@string/weekpicker_title"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_gravity="center_horizontal"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
-
- <!-- weeks -->
- <com.android.music.VerticalTextSpinner
- android:id="@+id/weeks"
- android:layout_width="120dip"
- android:layout_height="120dip"
- android:focusable="true"
- android:focusableInTouchMode="true"
- android:layout_gravity="center_horizontal"
- android:layout_marginTop="6dip"
- android:layout_marginBottom="6dip"
- />
-
- <!-- Set button -->
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:padding="6dip"
- android:background="#ffffff" >
-
- <Button android:id="@+id/set"
- android:layout_width="120dip"
- android:layout_height="wrap_content"
- android:text="@string/weekpicker_set"
- android:layout_alignParentLeft="true" />
-
- <Button android:id="@+id/cancel"
- android:layout_width="120dip"
- android:layout_height="wrap_content"
- android:text="@string/cancel"
- android:layout_alignParentRight="true" />
-
- </RelativeLayout>
-
-</LinearLayout>
-
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 3830a2c..26acd6c 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -76,12 +76,12 @@
<string name="tracks_title" msgid="3229389424532295124">"الأغاني"</string>
<string name="playlists_menu" msgid="5382792649771928849">"قوائم التشغيل"</string>
<string name="playlists_title" msgid="5094238486322957927">"قوائم التشغيل"</string>
- <string name="videos_title" msgid="2066741954354129115">"الفيديوهات"</string>
+ <string name="videos_title" msgid="2066741954354129115">"مقاطع الفيديو"</string>
<string name="all_title" msgid="6880186414437237653">"كل الوسائط"</string>
<string name="browse_menu" msgid="5248122473075843289">"الفنانون"</string>
<string name="search_title" msgid="1016971653383739344">"بحث"</string>
<string name="no_tracks_title" msgid="8805805388271238471">"ليس هناك أغاني"</string>
- <string name="no_videos_title" msgid="6218814130364793104">"ليس هناك أي فيديوهات"</string>
+ <string name="no_videos_title" msgid="6218814130364793104">"ليس هناك أي مقاطع فيديو"</string>
<string name="no_playlists_title" msgid="4456351945617594418">"لا قوائم تشغيل"</string>
<string name="delete_playlist_menu" msgid="8998637685583495247">"حذف"</string>
<string name="edit_playlist_menu" msgid="571618502105370684">"تعديل"</string>
@@ -154,7 +154,7 @@
<string name="musicbrowserlabel" msgid="3162022214114562892">"موسيقى"</string>
<string name="musicshortcutlabel" msgid="2602980193508150226">"قائمة تشغيل الموسيقى"</string>
<string name="mediaplaybacklabel" msgid="6733604841530940397">"موسيقى"</string>
- <string name="videobrowserlabel" msgid="8522326678447494657">"الفيديوهات"</string>
+ <string name="videobrowserlabel" msgid="8522326678447494657">"مقاطع الفيديو"</string>
<string name="mediapickerlabel" msgid="4549836003229914299">"موسيقى"</string>
<string name="playback_failed" msgid="3811851150820251398">"لا يتيح المشغل استخدام هذا النوع من الملفات الصوتية."</string>
<string name="cancel" msgid="886559484711947520">"إلغاء"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 06ca358..864309f 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -51,7 +51,7 @@
</plurals>
<string name="scanning" msgid="3529383847223198502">"Luetaan SD-korttia…"</string>
<string name="scanning_nosdcard" msgid="8105284774487360148">"Tarkistetaan USB-tallennustilaa…"</string>
- <string name="nowplaying_title" msgid="8342523844307751761">"Musiikintunnistus"</string>
+ <string name="nowplaying_title" msgid="8342523844307751761">"Nyt toistetaan"</string>
<string name="partyshuffle_title" msgid="6582413231529992125">"Bilesekoitus"</string>
<string name="artists_title" msgid="8490372367259160067">"Esittäjät"</string>
<string name="albums_menu" msgid="5807982055590211900">"Albumit"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 24fd5f3..ebeed9f 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -90,8 +90,8 @@
<string name="sdcard_error_message_nosdcard" msgid="4983430848526821234">"Foi encontrado um erro no seu armazenamento USB."</string>
<string name="unknown_artist_name" msgid="5567811106415855219">"Artista desconhecido"</string>
<string name="unknown_album_name" msgid="8525145988941244727">"Álbum desconhecido"</string>
- <string name="shuffle_on_notif" msgid="5453708337808483943">"A ordem aleatória está ativada."</string>
- <string name="shuffle_off_notif" msgid="4251189610017886263">"A ordem aleatória está desativada."</string>
+ <string name="shuffle_on_notif" msgid="5453708337808483943">"A reprodução aleatória está ativada."</string>
+ <string name="shuffle_off_notif" msgid="4251189610017886263">"A reprodução aleatória está desativada."</string>
<string name="repeat_off_notif" msgid="1149406899083479716">"A repetição está desativada."</string>
<string name="repeat_current_notif" msgid="1227153936360904196">"Repetindo a música atual."</string>
<string name="repeat_all_notif" msgid="6443293055987316642">"Repetindo todas as músicas."</string>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c7f9082..ca0174d 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -328,6 +328,7 @@
<string name="play_pause">play or pause</string>
<string name="skip_next">Skip to next</string>
<string name="no_search_results">No search results.</string>
+ <string name="message_seekbar">Setting Seekbar max to %d sec</string>
</resources>
diff --git a/res/xml/appwidget_info.xml b/res/xml/appwidget_info.xml
deleted file mode 100644
index 30b762c..0000000
--- a/res/xml/appwidget_info.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
- android:minWidth="294dip"
- android:minHeight="72dip"
- android:updatePeriodMillis="0"
- android:initialLayout="@layout/album_appwidget"
- >
-</appwidget-provider>
diff --git a/res/xml/automotive_app_desc.xml b/res/xml/automotive_app_desc.xml
deleted file mode 100644
index 0a6a3c9..0000000
--- a/res/xml/automotive_app_desc.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<automotiveApp>
- <uses name="media"/>
-</automotiveApp>
\ No newline at end of file
diff --git a/res/xml/searchable.xml b/res/xml/searchable.xml
deleted file mode 100644
index 2cfd796..0000000
--- a/res/xml/searchable.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<searchable xmlns:android="http://schemas.android.com/apk/res/android"
- android:label="@string/search_title"
- android:hint="@string/search_hint"
- android:includeInGlobalSearch="true"
-
- android:searchSuggestAuthority="media"
- android:searchSuggestPath="external/audio/search"
- android:searchSuggestThreshold="3"
- android:searchSuggestIntentAction="android.intent.action.VIEW"
- android:searchSettingsDescription="@string/search_settings_description"
-/>
diff --git a/src/com/android/music/AlbumBrowserActivity.java b/src/com/android/music/AlbumBrowserActivity.java
deleted file mode 100644
index ce5dcab..0000000
--- a/src/com/android/music/AlbumBrowserActivity.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music;
-
-import android.app.ListActivity;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.media.AudioManager;
-import android.media.MediaDescription;
-import android.media.MediaMetadata;
-import android.media.browse.MediaBrowser;
-import android.media.session.MediaController;
-import android.media.session.MediaSession;
-import android.media.session.PlaybackState;
-import android.net.Uri;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.widget.*;
-import com.android.music.utils.LogHelper;
-import com.android.music.utils.MediaIDHelper;
-import com.android.music.utils.Playback;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/*
-This activity is the albums browsing tab
- */
-public class AlbumBrowserActivity extends ListActivity {
- private static final String TAG = LogHelper.makeLogTag(AlbumBrowserActivity.class);
- private static final MediaBrowser.MediaItem DEFAULT_PARENT_ITEM =
- new MediaBrowser.MediaItem(new MediaDescription.Builder()
- .setMediaId(MediaIDHelper.MEDIA_ID_MUSICS_BY_ALBUM)
- .build(),
- MediaBrowser.MediaItem.FLAG_BROWSABLE);
-
- private ListView mAlbumList;
- private AlbumBrowseAdapter mBrowseListAdapter;
- private MediaBrowser mMediaBrowser;
- private MediaBrowser.MediaItem mParentItem;
-
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle icicle) {
- Log.d(TAG, "onCreate()");
- super.onCreate(icicle);
- if (icicle != null) {
- mParentItem = icicle.getParcelable(MusicUtils.TAG_PARENT_ITEM);
- } else if (getIntent() != null) {
- mParentItem = getIntent().getExtras().getParcelable(MusicUtils.TAG_PARENT_ITEM);
- }
- if (mParentItem == null) {
- mParentItem = DEFAULT_PARENT_ITEM;
- }
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setVolumeControlStream(AudioManager.STREAM_MUSIC);
-
- setContentView(R.layout.media_picker_activity);
- MusicUtils.updateButtonBar(this, R.id.albumtab);
- mAlbumList = getListView();
- mAlbumList.setOnCreateContextMenuListener(this);
- mAlbumList.setTextFilterEnabled(true);
-
- mBrowseListAdapter = (AlbumBrowseAdapter) getLastNonConfigurationInstance();
- if (mBrowseListAdapter == null) {
- // Log.i("@@@", "starting query");
- mBrowseListAdapter = new AlbumBrowseAdapter(this, R.layout.track_list_item);
- setTitle(R.string.working_albums);
- }
- setListAdapter(mBrowseListAdapter);
- Log.d(TAG, "Creating MediaBrowser");
- mMediaBrowser = new MediaBrowser(this, new ComponentName(this, MediaPlaybackService.class),
- mConnectionCallback, null);
- }
-
- @Override
- public void onDestroy() {
- Log.d(TAG, "onDestroy()");
- ListView lv = getListView();
- // Because we pass the adapter to the next activity, we need to make
- // sure it doesn't keep a reference to this activity. We can do this
- // by clearing its DatasetObservers, which setListAdapter(null) does.
- setListAdapter(null);
- mBrowseListAdapter = null;
- super.onDestroy();
- }
-
- @Override
- public void onResume() {
- Log.d(TAG, "onResume()");
- super.onResume();
- }
-
- @Override
- public void onStart() {
- Log.d(TAG, "onStart()");
- super.onStart();
- mMediaBrowser.connect();
- }
-
- @Override
- public void onStop() {
- Log.d(TAG, "onStop()");
- super.onStop();
- mMediaBrowser.disconnect();
- }
-
- @Override
- public void onPause() {
- Log.d(TAG, "onPause()");
- super.onPause();
- }
-
- @Override
- public void onSaveInstanceState(Bundle outcicle) {
- outcicle.putParcelable(MusicUtils.TAG_PARENT_ITEM, mParentItem);
- super.onSaveInstanceState(outcicle);
- }
-
- private void setTitle() {
- CharSequence fancyName = "";
- setTitle(R.string.albums_title);
- }
-
- private MediaBrowser.SubscriptionCallback mSubscriptionCallback =
- new MediaBrowser.SubscriptionCallback() {
-
- @Override
- public void onChildrenLoaded(
- String parentId, List<MediaBrowser.MediaItem> children) {
- mBrowseListAdapter.clear();
- mBrowseListAdapter.notifyDataSetInvalidated();
- for (MediaBrowser.MediaItem item : children) {
- mBrowseListAdapter.add(item);
- }
- mBrowseListAdapter.notifyDataSetChanged();
- }
-
- @Override
- public void onError(String id) {
- Toast.makeText(getApplicationContext(), R.string.error_loading_media,
- Toast.LENGTH_LONG)
- .show();
- }
- };
-
- private MediaBrowser.ConnectionCallback mConnectionCallback =
- new MediaBrowser.ConnectionCallback() {
- @Override
- public void onConnected() {
- Log.d(TAG, "onConnected: session token " + mMediaBrowser.getSessionToken());
- mMediaBrowser.subscribe(mParentItem.getMediaId(), mSubscriptionCallback);
- if (mMediaBrowser.getSessionToken() == null) {
- throw new IllegalArgumentException("No Session token");
- }
- MediaController mediaController = new MediaController(
- AlbumBrowserActivity.this, mMediaBrowser.getSessionToken());
- mediaController.registerCallback(mMediaControllerCallback);
- AlbumBrowserActivity.this.setMediaController(mediaController);
- if (mediaController.getMetadata() != null) {
- MusicUtils.updateNowPlaying(AlbumBrowserActivity.this);
- }
- }
-
- @Override
- public void onConnectionFailed() {
- Log.d(TAG, "onConnectionFailed");
- }
-
- @Override
- public void onConnectionSuspended() {
- Log.d(TAG, "onConnectionSuspended");
- AlbumBrowserActivity.this.setMediaController(null);
- }
- };
-
- private MediaController.Callback mMediaControllerCallback = new MediaController.Callback() {
- @Override
- public void onMetadataChanged(MediaMetadata metadata) {
- super.onMetadataChanged(metadata);
- MusicUtils.updateNowPlaying(AlbumBrowserActivity.this);
- if (mBrowseListAdapter != null) {
- mBrowseListAdapter.notifyDataSetChanged();
- }
- }
- };
-
- // An adapter for showing the list of browsed MediaItem's
- private class AlbumBrowseAdapter extends ArrayAdapter<MediaBrowser.MediaItem> {
- private final Drawable mNowPlayingOverlay;
- private final BitmapDrawable mDefaultAlbumIcon;
- private int mLayoutId;
-
- private class ViewHolder {
- TextView line1;
- TextView line2;
- ImageView play_indicator;
- ImageView icon;
- }
-
- AlbumBrowseAdapter(Context context, int layout) {
- super(context, layout, new ArrayList<>());
- mNowPlayingOverlay = context.getResources().getDrawable(
- R.drawable.indicator_ic_mp_playing_list, context.getTheme());
- Bitmap b = BitmapFactory.decodeResource(
- context.getResources(), R.drawable.albumart_mp_unknown_list);
- mDefaultAlbumIcon = new BitmapDrawable(context.getResources(), b);
- // no filter or dither, it's a lot faster and we can't tell the difference
- mDefaultAlbumIcon.setFilterBitmap(false);
- mDefaultAlbumIcon.setDither(false);
- mLayoutId = layout;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- Log.d(TAG, "getView()");
- if (convertView == null) {
- convertView = LayoutInflater.from(getContext()).inflate(mLayoutId, parent, false);
- ViewHolder vh = new ViewHolder();
- vh.line1 = (TextView) convertView.findViewById(R.id.line1);
- vh.line2 = (TextView) convertView.findViewById(R.id.line2);
- vh.play_indicator = (ImageView) convertView.findViewById(R.id.play_indicator);
- vh.icon = (ImageView) convertView.findViewById(R.id.icon);
- vh.icon.setBackground(mDefaultAlbumIcon);
- vh.icon.setPadding(0, 0, 1, 0);
- vh.icon.setVisibility(View.VISIBLE);
- convertView.setTag(vh);
- }
- ViewHolder vh = (ViewHolder) convertView.getTag();
- MediaBrowser.MediaItem item = getItem(position);
- Log.d(TAG, "Album: " + item.getDescription().getTitle());
- vh.line1.setText(item.getDescription().getTitle());
- Log.d(TAG, "Artist: " + item.getDescription().getSubtitle());
- vh.line2.setText(item.getDescription().getSubtitle());
- Bitmap albumArt = item.getDescription().getIconBitmap();
- LogHelper.d(TAG, "looking for album art");
- if (albumArt != null) {
- vh.icon.setImageDrawable(MusicUtils.getDrawableBitmap(albumArt, mDefaultAlbumIcon));
- } else {
- vh.icon.setImageDrawable(mDefaultAlbumIcon);
- }
- MediaController mediaController = AlbumBrowserActivity.this.getMediaController();
- if (mediaController == null) {
- vh.play_indicator.setImageDrawable(null);
- return convertView;
- }
- MediaMetadata metadata = mediaController.getMetadata();
- if (metadata == null) {
- vh.play_indicator.setImageDrawable(null);
- return convertView;
- }
- if (metadata.getString(MediaMetadata.METADATA_KEY_ALBUM)
- .equals(item.getDescription().getTitle())) {
- vh.play_indicator.setImageDrawable(mNowPlayingOverlay);
- } else {
- vh.play_indicator.setImageDrawable(null);
- }
- return convertView;
- }
- }
-
- @Override
- protected void onListItemClick(ListView l, View v, int position, long id) {
- Log.d(TAG, "onListItemClick at position " + position + ", id " + id);
- MediaBrowser.MediaItem item = mBrowseListAdapter.getItem(position);
- if (item.isBrowsable()) {
- Intent intent = new Intent(Intent.ACTION_PICK);
- intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track");
- intent.putExtra(MusicUtils.TAG_PARENT_ITEM, item);
- intent.putExtra(MusicUtils.TAG_WITH_TABS, false);
- startActivity(intent);
- }
- }
-}
diff --git a/src/com/android/music/ArtistAlbumBrowserActivity.java b/src/com/android/music/ArtistAlbumBrowserActivity.java
deleted file mode 100644
index ffccd32..0000000
--- a/src/com/android/music/ArtistAlbumBrowserActivity.java
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music;
-
-import android.app.ExpandableListActivity;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.media.AudioManager;
-import android.media.MediaDescription;
-import android.media.MediaMetadata;
-import android.media.browse.MediaBrowser;
-import android.media.session.MediaController;
-import android.net.Uri;
-import android.os.Bundle;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.widget.ExpandableListView;
-import android.widget.ImageView;
-import android.widget.SimpleExpandableListAdapter;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import com.android.music.utils.LogHelper;
-import com.android.music.utils.MediaIDHelper;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-public class ArtistAlbumBrowserActivity extends ExpandableListActivity {
- private static final String TAG = LogHelper.makeLogTag(ArtistAlbumBrowserActivity.class);
- private static final String KEY_NUM_ALBUMS = "__NUM_ALBUMS__";
- private static final MediaBrowser.MediaItem DEFAULT_PARENT_ITEM =
- new MediaBrowser.MediaItem(new MediaDescription.Builder()
- .setMediaId(MediaIDHelper.MEDIA_ID_MUSICS_BY_ARTIST)
- .build(),
- MediaBrowser.MediaItem.FLAG_BROWSABLE);
-
- private ArtistAlbumListAdapter mAdapter;
- private MediaBrowser mMediaBrowser;
- private MediaBrowser.MediaItem mParentItem;
-
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- LogHelper.d(TAG, "onCreate()");
- // Handle past states
- if (icicle != null) {
- mParentItem = icicle.getParcelable(MusicUtils.TAG_PARENT_ITEM);
- } else if (getIntent() != null) {
- mParentItem = getIntent().getExtras().getParcelable(MusicUtils.TAG_PARENT_ITEM);
- }
- if (mParentItem == null) {
- mParentItem = DEFAULT_PARENT_ITEM;
- }
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setVolumeControlStream(AudioManager.STREAM_MUSIC);
-
- // Init layout
- setContentView(R.layout.media_picker_activity_expanding);
- MusicUtils.updateButtonBar(this, R.id.artisttab);
-
- // Init expandable list
- ExpandableListView lv = getExpandableListView();
- lv.setTextFilterEnabled(true);
- mAdapter = (ArtistAlbumListAdapter) getLastNonConfigurationInstance();
- if (mAdapter == null) {
- // Log.i("@@@", "starting query");
- mAdapter = new ArtistAlbumListAdapter(this, new ArrayList<>(), new ArrayList<>());
- setListAdapter(mAdapter);
- setTitle(R.string.working_artists);
- } else {
- mAdapter.setActivity(this);
- }
- setListAdapter(mAdapter);
- LogHelper.d(TAG, "Creating MediaBrowser");
- mMediaBrowser = new MediaBrowser(this, new ComponentName(this, MediaPlaybackService.class),
- mConnectionCallback, null);
- }
-
- @Override
- public Object onRetainNonConfigurationInstance() {
- return mAdapter;
- }
-
- @Override
- public void onSaveInstanceState(Bundle outcicle) {
- outcicle.putParcelable(MusicUtils.TAG_PARENT_ITEM, mParentItem);
- super.onSaveInstanceState(outcicle);
- }
-
- @Override
- public void onDestroy() {
- setListAdapter(null);
- mAdapter = null;
- setListAdapter(null);
- super.onDestroy();
- }
-
- @Override
- public void onStart() {
- LogHelper.d(TAG, "onStart()");
- super.onStart();
- mMediaBrowser.connect();
- }
-
- @Override
- public void onStop() {
- LogHelper.d(TAG, "onStop()");
- super.onStop();
- mMediaBrowser.disconnect();
- }
-
- private MediaBrowser
- .SubscriptionCallback mSubscriptionCallback = new MediaBrowser.SubscriptionCallback() {
- @Override
- public void onChildrenLoaded(String parentId, List<MediaBrowser.MediaItem> children) {
- if (parentId.equals(MediaIDHelper.MEDIA_ID_MUSICS_BY_ARTIST)) {
- mAdapter.getArtistMap().clear();
- mAdapter.getGroupData().clear();
- mAdapter.notifyDataSetInvalidated();
- for (MediaBrowser.MediaItem item : children) {
- ConcurrentHashMap<String, MediaBrowser.MediaItem> entry =
- new ConcurrentHashMap<>();
- entry.put(MediaIDHelper.MEDIA_ID_MUSICS_BY_ARTIST, item);
- synchronized (this) {
- mAdapter.getArtistMap().put(item.getDescription().getTitle().toString(),
- mAdapter.getGroupData().size());
- mAdapter.getGroupData().add(entry);
- mAdapter.getChildData().add(new ArrayList<>());
- }
- mMediaBrowser.subscribe(item.getMediaId(), this);
- }
- mAdapter.notifyDataSetChanged();
- } else if (parentId.startsWith(MediaIDHelper.MEDIA_ID_MUSICS_BY_ARTIST)) {
- String artist = MediaIDHelper.getHierarchy(parentId)[1];
- if (!mAdapter.getArtistMap().containsKey(artist)) {
- return;
- }
- int artistIndex = mAdapter.getArtistMap().get(artist);
- mAdapter.getChildData().get(artistIndex).clear();
- mAdapter.notifyDataSetInvalidated();
- Bundle extras = new Bundle();
- extras.putLong(KEY_NUM_ALBUMS, children.size());
- MediaBrowser.MediaItem newArtistItem =
- new MediaBrowser.MediaItem(new MediaDescription.Builder()
- .setMediaId("Count")
- .setExtras(extras)
- .build(),
- 0);
- mAdapter.getGroupData().get(artistIndex).put(KEY_NUM_ALBUMS, newArtistItem);
- for (MediaBrowser.MediaItem item : children) {
- ConcurrentHashMap<String, MediaBrowser.MediaItem> entry =
- new ConcurrentHashMap<>();
- entry.put(MediaIDHelper.MEDIA_ID_MUSICS_BY_ALBUM, item);
- mAdapter.getChildData().get(artistIndex).add(entry);
- }
- mAdapter.notifyDataSetChanged();
- }
- }
-
- @Override
- public void onError(String id) {
- Toast.makeText(getApplicationContext(), R.string.error_loading_media, Toast.LENGTH_LONG)
- .show();
- }
- };
-
- private MediaBrowser.ConnectionCallback mConnectionCallback =
- new MediaBrowser.ConnectionCallback() {
- @Override
- public void onConnected() {
- LogHelper.d(
- TAG, "onConnected: session token ", mMediaBrowser.getSessionToken());
- mMediaBrowser.subscribe(mParentItem.getMediaId(), mSubscriptionCallback);
- if (mMediaBrowser.getSessionToken() == null) {
- throw new IllegalArgumentException("No Session token");
- }
- MediaController mediaController = new MediaController(
- ArtistAlbumBrowserActivity.this, mMediaBrowser.getSessionToken());
- mediaController.registerCallback(mMediaControllerCallback);
- ArtistAlbumBrowserActivity.this.setMediaController(mediaController);
- if (mediaController.getMetadata() != null) {
- MusicUtils.updateNowPlaying(ArtistAlbumBrowserActivity.this);
- }
- }
-
- @Override
- public void onConnectionFailed() {
- LogHelper.d(TAG, "onConnectionFailed");
- }
-
- @Override
- public void onConnectionSuspended() {
- LogHelper.d(TAG, "onConnectionSuspended");
- ArtistAlbumBrowserActivity.this.setMediaController(null);
- }
- };
-
- private MediaController.Callback mMediaControllerCallback = new MediaController.Callback() {
- @Override
- public void onMetadataChanged(MediaMetadata metadata) {
- super.onMetadataChanged(metadata);
- MusicUtils.updateNowPlaying(ArtistAlbumBrowserActivity.this);
- }
- };
-
- private class ArtistAlbumListAdapter extends SimpleExpandableListAdapter {
- private final Drawable mNowPlayingOverlay;
- private final BitmapDrawable mDefaultAlbumIcon;
- private ArtistAlbumBrowserActivity mActivity;
- private ArrayList<ConcurrentHashMap<String, MediaBrowser.MediaItem>> mGroupData;
- private ArrayList < ArrayList
- < ConcurrentHashMap<String, MediaBrowser.MediaItem>>> mChildData;
- private ConcurrentHashMap<String, Integer> mArtistMap;
-
- private class ViewHolder {
- TextView line1;
- TextView line2;
- ImageView play_indicator;
- ImageView icon;
- }
-
- ArtistAlbumListAdapter(ArtistAlbumBrowserActivity currentActivity,
- ArrayList<ConcurrentHashMap<String, MediaBrowser.MediaItem>> groupData,
- ArrayList < ArrayList
- < ConcurrentHashMap<String, MediaBrowser.MediaItem>>> childData) {
- super(currentActivity, groupData, R.layout.track_list_item_group, new String[] {},
- new int[] {}, childData, R.layout.track_list_item_child, new String[] {},
- new int[] {});
- mGroupData = groupData;
- mChildData = childData;
- mActivity = currentActivity;
- mNowPlayingOverlay = currentActivity.getResources().getDrawable(
- R.drawable.indicator_ic_mp_playing_list, currentActivity.getTheme());
- mDefaultAlbumIcon = (BitmapDrawable) currentActivity.getResources().getDrawable(
- R.drawable.albumart_mp_unknown_list, currentActivity.getTheme());
- // no filter or dither, it's a lot faster and we can't tell the difference
- mDefaultAlbumIcon.setFilterBitmap(false);
- mDefaultAlbumIcon.setDither(false);
- mArtistMap = new ConcurrentHashMap<>();
- }
-
- public ArrayList<ConcurrentHashMap<String, MediaBrowser.MediaItem>> getGroupData() {
- return mGroupData;
- }
-
- public ArrayList < ArrayList
- < ConcurrentHashMap<String, MediaBrowser.MediaItem>>> getChildData() {
- return mChildData;
- }
-
- public Map<String, Integer> getArtistMap() {
- return mArtistMap;
- }
-
- public void setActivity(ArtistAlbumBrowserActivity newactivity) {
- mActivity = newactivity;
- }
-
- @Override
- public View newGroupView(boolean isExpanded, ViewGroup parent) {
- View v = super.newGroupView(isExpanded, parent);
- ImageView iv = (ImageView) v.findViewById(R.id.icon);
- ViewGroup.LayoutParams p = iv.getLayoutParams();
- p.width = ViewGroup.LayoutParams.WRAP_CONTENT;
- p.height = ViewGroup.LayoutParams.WRAP_CONTENT;
- ViewHolder vh = new ViewHolder();
- vh.line1 = (TextView) v.findViewById(R.id.line1);
- vh.line2 = (TextView) v.findViewById(R.id.line2);
- vh.play_indicator = (ImageView) v.findViewById(R.id.play_indicator);
- vh.icon = (ImageView) v.findViewById(R.id.icon);
- vh.icon.setPadding(0, 0, 1, 0);
- v.setTag(vh);
- return v;
- }
-
- @Override
- public View newChildView(boolean isLastChild, ViewGroup parent) {
- View v = super.newChildView(isLastChild, parent);
- ViewHolder vh = new ViewHolder();
- vh.line1 = (TextView) v.findViewById(R.id.line1);
- vh.line2 = (TextView) v.findViewById(R.id.line2);
- vh.play_indicator = (ImageView) v.findViewById(R.id.play_indicator);
- vh.icon = (ImageView) v.findViewById(R.id.icon);
- vh.icon.setBackground(mDefaultAlbumIcon);
- vh.icon.setPadding(0, 0, 1, 0);
- v.setTag(vh);
- return v;
- }
-
- @Override
- public View getGroupView(
- int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = newGroupView(isExpanded, parent);
- }
- Map<String, MediaBrowser.MediaItem> artistEntry =
- (Map<String, MediaBrowser.MediaItem>) getGroup(groupPosition);
- MediaBrowser.MediaItem artistItem =
- artistEntry.get(MediaIDHelper.MEDIA_ID_MUSICS_BY_ARTIST);
- MediaBrowser.MediaItem countItem = artistEntry.get(KEY_NUM_ALBUMS);
- ViewHolder vh = (ViewHolder) convertView.getTag();
- vh.line1.setText(artistItem.getDescription().getTitle());
- int numalbums = -1;
- if (countItem != null) {
- Bundle extras = countItem.getDescription().getExtras();
- if (extras != null) {
- numalbums = (int) extras.getLong(KEY_NUM_ALBUMS);
- }
- }
- String songs_albums = MusicUtils.makeAlbumsLabel(mActivity, numalbums, -1, false);
- vh.line2.setText(songs_albums);
- MediaController mediaController = mActivity.getMediaController();
- if (mediaController == null) {
- vh.play_indicator.setImageDrawable(null);
- return convertView;
- }
- MediaMetadata metadata = mediaController.getMetadata();
- if (metadata == null) {
- vh.play_indicator.setImageDrawable(null);
- return convertView;
- }
- if (metadata.getString(MediaMetadata.METADATA_KEY_ARTIST)
- .equals(artistItem.getDescription().getTitle())
- && !isExpanded) {
- vh.play_indicator.setImageDrawable(mNowPlayingOverlay);
- } else {
- vh.play_indicator.setImageDrawable(null);
- }
- return convertView;
- }
-
- @Override
- public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
- View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = newChildView(isLastChild, parent);
- }
- Map<String, MediaBrowser.MediaItem> albumEntry =
- (Map<String, MediaBrowser.MediaItem>) getChild(groupPosition, childPosition);
- MediaBrowser.MediaItem albumItem =
- albumEntry.get(MediaIDHelper.MEDIA_ID_MUSICS_BY_ALBUM);
- ViewHolder vh = (ViewHolder) convertView.getTag();
- vh.line1.setText(albumItem.getDescription().getTitle());
- vh.line2.setText(albumItem.getDescription().getDescription());
- Bitmap albumArt = albumItem.getDescription().getIconBitmap();
- if (albumArt == null) {
- vh.icon.setBackground(mDefaultAlbumIcon);
- } else {
- vh.icon.setImageDrawable(MusicUtils.getDrawableBitmap(albumArt, mDefaultAlbumIcon));
- }
- MediaController mediaController = mActivity.getMediaController();
- if (mediaController == null) {
- vh.play_indicator.setImageDrawable(null);
- return convertView;
- }
- MediaMetadata metadata = mediaController.getMetadata();
- if (metadata == null) {
- vh.play_indicator.setImageDrawable(null);
- return convertView;
- }
- if (albumItem.getDescription().getTitle().equals(
- metadata.getString(MediaMetadata.METADATA_KEY_ALBUM))) {
- vh.play_indicator.setImageDrawable(mNowPlayingOverlay);
- } else {
- vh.play_indicator.setImageDrawable(null);
- }
- return convertView;
- }
- }
-
- @Override
- public boolean onChildClick(
- ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
- Map<String, MediaBrowser.MediaItem> albumEntry =
- (Map<String, MediaBrowser.MediaItem>) mAdapter.getChild(
- groupPosition, childPosition);
- Intent intent = new Intent(Intent.ACTION_PICK);
- intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track");
- intent.putExtra(
- MusicUtils.TAG_PARENT_ITEM, albumEntry.get(MediaIDHelper.MEDIA_ID_MUSICS_BY_ALBUM));
- startActivity(intent);
- return true;
- }
-}
diff --git a/src/com/android/music/MediaPlaybackActivity.java b/src/com/android/music/MediaPlaybackActivity.java
deleted file mode 100644
index 6b83073..0000000
--- a/src/com/android/music/MediaPlaybackActivity.java
+++ /dev/null
@@ -1,737 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music;
-
-import android.app.Activity;
-import android.app.SearchManager;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.drawable.BitmapDrawable;
-import android.media.AudioManager;
-import android.media.MediaDescription;
-import android.media.MediaMetadata;
-import android.media.browse.MediaBrowser;
-import android.media.session.MediaController;
-import android.media.session.PlaybackState;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.SystemClock;
-import android.provider.MediaStore;
-import android.text.Layout;
-import android.text.TextUtils.TruncateAt;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.Window;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.ProgressBar;
-import android.widget.SeekBar;
-import android.widget.SeekBar.OnSeekBarChangeListener;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import com.android.music.utils.LogHelper;
-import com.android.music.utils.MediaIDHelper;
-import com.android.music.utils.MusicProvider;
-
-/*
-This is the Now Playing Activity
- */
-public class MediaPlaybackActivity
- extends Activity implements View.OnTouchListener, View.OnLongClickListener {
- private static final String TAG = LogHelper.makeLogTag(MediaPlaybackActivity.class);
-
- private long mStartSeekPos = 0;
- private long mLastSeekEventTime;
- private RepeatingImageButton mPrevButton;
- private ImageButton mPlayPauseButton;
- private RepeatingImageButton mNextButton;
- private ImageButton mRepeatButton;
- private ImageButton mShuffleButton;
- private ImageButton mQueueButton;
- private int mTouchSlop;
-
- private ImageView mAlbumArt;
- private TextView mCurrentTime;
- private TextView mTotalTime;
- private TextView mArtistName;
- private TextView mAlbumName;
- private TextView mTrackName;
- private LinearLayout mTrackInfo;
- private ProgressBar mProgress;
- private BitmapDrawable mDefaultAlbumArt;
- private Toast mToast;
-
- private MediaBrowser mMediaBrowser;
- private final Handler mHandler = new Handler();
-
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle icicle) {
- LogHelper.d(TAG, "onCreate()");
- super.onCreate(icicle);
- setVolumeControlStream(AudioManager.STREAM_MUSIC);
-
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.audio_player);
-
- mCurrentTime = (TextView) findViewById(R.id.currenttime);
- mTotalTime = (TextView) findViewById(R.id.totaltime);
- mProgress = (ProgressBar) findViewById(android.R.id.progress);
- mAlbumArt = (ImageView) findViewById(R.id.album);
- mArtistName = (TextView) findViewById(R.id.artistname);
- mAlbumName = (TextView) findViewById(R.id.albumname);
- mTrackName = (TextView) findViewById(R.id.trackname);
- mTrackInfo = (LinearLayout) findViewById(R.id.trackinfo);
-
- Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.albumart_mp_unknown);
- mDefaultAlbumArt = new BitmapDrawable(getResources(), b);
- // no filter or dither, it's a lot faster and we can't tell the difference
- mDefaultAlbumArt.setFilterBitmap(false);
- mDefaultAlbumArt.setDither(false);
-
- /* Set metadata listeners */
- View v = (View) mArtistName.getParent();
- v.setOnTouchListener(this);
- v.setOnLongClickListener(this);
- v = (View) mAlbumName.getParent();
- v.setOnTouchListener(this);
- v.setOnLongClickListener(this);
- v = (View) mTrackName.getParent();
- v.setOnTouchListener(this);
- v.setOnLongClickListener(this);
-
- /* Set button listeners */
- mPrevButton = (RepeatingImageButton) findViewById(R.id.prev);
- mPrevButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- if (getMediaController() == null) return;
- if (getMediaController().getPlaybackState().getPosition() < 2000) {
- getMediaController().getTransportControls().skipToPrevious();
- } else {
- getMediaController().getTransportControls().seekTo(0);
- getMediaController().getTransportControls().play();
- }
- }
- });
- mPrevButton.setRepeatListener(new RepeatingImageButton.RepeatListener() {
- public void onRepeat(View v, long howlong, int repcnt) {
- scanBackward(repcnt, howlong);
- }
- }, 260);
- mPlayPauseButton = (ImageButton) findViewById(R.id.pause);
- mPlayPauseButton.requestFocus();
- mPlayPauseButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- if (getMediaController() != null) {
- if (getMediaController().getPlaybackState().getState()
- != PlaybackState.STATE_PLAYING) {
- getMediaController().getTransportControls().play();
- } else {
- getMediaController().getTransportControls().pause();
- }
- }
- }
- });
- mNextButton = (RepeatingImageButton) findViewById(R.id.next);
- mNextButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- if (getMediaController() == null) return;
- getMediaController().getTransportControls().skipToNext();
- }
- });
- mNextButton.setRepeatListener(new RepeatingImageButton.RepeatListener() {
- public void onRepeat(View v, long howlong, int repcnt) {
- scanForward(repcnt, howlong);
- }
- }, 260);
- mQueueButton = (ImageButton) findViewById(R.id.curplaylist);
- mQueueButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- LogHelper.d(TAG, "mQueueButton onClick");
- MediaBrowser.MediaItem parentItem = new MediaBrowser.MediaItem(
- new MediaDescription.Builder()
- .setMediaId(MediaIDHelper.createBrowseCategoryMediaID(
- MediaIDHelper.MEDIA_ID_MUSICS_BY_PLAYLIST,
- MediaIDHelper.MEDIA_ID_NOW_PLAYING))
- .setTitle("Now Playing")
- .build(),
- MediaBrowser.MediaItem.FLAG_BROWSABLE);
- Intent intent = new Intent(Intent.ACTION_PICK)
- .setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track")
- .putExtra(MusicUtils.TAG_WITH_TABS, false)
- .putExtra(MusicUtils.TAG_PARENT_ITEM, parentItem);
- startActivity(intent);
- }
- });
- mShuffleButton = ((ImageButton) findViewById(R.id.shuffle));
- mShuffleButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- toggleShuffle();
- }
- });
- mRepeatButton = ((ImageButton) findViewById(R.id.repeat));
- mRepeatButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- LogHelper.d(TAG, "Repeat button clicked");
- if (getMediaController() == null) return;
- Bundle extras = getMediaController().getExtras();
- if (extras == null) return;
- MediaPlaybackService.RepeatMode repeatMode =
- MediaPlaybackService.RepeatMode
- .values()[extras.getInt(MediaPlaybackService.REPEAT_MODE)];
- MediaPlaybackService.RepeatMode nextRepeatMode;
- switch (repeatMode) {
- case REPEAT_NONE:
- nextRepeatMode = MediaPlaybackService.RepeatMode.REPEAT_ALL;
- showToast(R.string.repeat_all_notif);
- break;
- case REPEAT_ALL:
- nextRepeatMode = MediaPlaybackService.RepeatMode.REPEAT_CURRENT;
- showToast(R.string.repeat_current_notif);
- break;
- case REPEAT_CURRENT:
- default:
- nextRepeatMode = MediaPlaybackService.RepeatMode.REPEAT_NONE;
- showToast(R.string.repeat_off_notif);
- break;
- }
- setRepeatMode(nextRepeatMode);
- // TODO(siyuanh): Should use a callback to register changes on service side
- setRepeatButtonImage(nextRepeatMode);
- }
- });
-
- if (mProgress instanceof SeekBar) {
- SeekBar seeker = (SeekBar) mProgress;
- seeker.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
- boolean mmFromTouch = false;
- public void onStartTrackingTouch(SeekBar bar) {
- mLastSeekEventTime = 0;
- mmFromTouch = true;
- }
- public void onProgressChanged(SeekBar bar, int progress, boolean fromuser) {
- if (!fromuser || (getMediaController() == null)) return;
- long now = SystemClock.elapsedRealtime();
- if ((now - mLastSeekEventTime) > 250) {
- mLastSeekEventTime = now;
- long duration = getMediaController().getMetadata().getLong(
- MediaMetadata.METADATA_KEY_DURATION);
- long position = duration * progress / 1000;
- getMediaController().getTransportControls().seekTo(position);
- // trackball event, allow progress updates
- if (!mmFromTouch) {
- updateProgressBar();
- }
- }
- }
- public void onStopTrackingTouch(SeekBar bar) {
- mmFromTouch = false;
- }
- });
- } else {
- LogHelper.d(TAG, "Seeking not supported");
- }
- mProgress.setMax(1000);
-
- mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();
-
- Log.d(TAG, "Creating MediaBrowser");
- mMediaBrowser = new MediaBrowser(this, new ComponentName(this, MediaPlaybackService.class),
- mConnectionCallback, null);
- }
-
- // Receive callbacks from the MediaController. Here we update our state such as which queue
- // is being shown, the current title and description and the PlaybackState.
- private MediaController.Callback mMediaControllerCallback = new MediaController.Callback() {
-
- @Override
- public void onSessionDestroyed() {
- LogHelper.d(TAG, "Session destroyed. Need to fetch a new Media Session");
- }
-
- @Override
- public void onPlaybackStateChanged(PlaybackState state) {
- if (state == null) {
- return;
- }
- LogHelper.d(TAG, "Received playback state change to state ", state.toString());
- updateProgressBar();
- setPauseButtonImage();
- }
-
- @Override
- public void onMetadataChanged(MediaMetadata metadata) {
- if (metadata == null) {
- return;
- }
- LogHelper.d(TAG, "Received updated metadata: ", metadata);
- updateTrackInfo();
- }
- };
-
- private MediaBrowser.ConnectionCallback mConnectionCallback =
- new MediaBrowser.ConnectionCallback() {
- @Override
- public void onConnected() {
- Log.d(TAG, "onConnected: session token " + mMediaBrowser.getSessionToken());
- if (mMediaBrowser.getSessionToken() == null) {
- throw new IllegalArgumentException("No Session token");
- }
- MediaController mediaController = new MediaController(
- MediaPlaybackActivity.this, mMediaBrowser.getSessionToken());
- mediaController.registerCallback(mMediaControllerCallback);
- MediaPlaybackActivity.this.setMediaController(mediaController);
- mRepeatButton.setVisibility(View.VISIBLE);
- mShuffleButton.setVisibility(View.VISIBLE);
- mQueueButton.setVisibility(View.VISIBLE);
- setRepeatButtonImage(null);
- setShuffleButtonImage();
- setPauseButtonImage();
- updateTrackInfo();
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- long delay = updateProgressBar();
- mHandler.postDelayed(this, delay);
- }
- });
- }
-
- @Override
- public void onConnectionFailed() {
- Log.d(TAG, "onConnectionFailed");
- }
-
- @Override
- public void onConnectionSuspended() {
- Log.d(TAG, "onConnectionSuspended");
- mHandler.removeCallbacksAndMessages(null);
- MediaPlaybackActivity.this.setMediaController(null);
- }
- };
-
- int mInitialX = -1;
- int mLastX = -1;
- int mTextWidth = 0;
- int mViewWidth = 0;
- boolean mDraggingLabel = false;
-
- TextView textViewForContainer(View v) {
- View vv = v.findViewById(R.id.artistname);
- if (vv != null) return (TextView) vv;
- vv = v.findViewById(R.id.albumname);
- if (vv != null) return (TextView) vv;
- vv = v.findViewById(R.id.trackname);
- if (vv != null) return (TextView) vv;
- return null;
- }
-
- public boolean onTouch(View v, MotionEvent event) {
- int action = event.getAction();
- TextView tv = textViewForContainer(v);
- if (tv == null) {
- return false;
- }
- if (action == MotionEvent.ACTION_DOWN) {
- v.setBackgroundColor(0xff606060);
- mInitialX = mLastX = (int) event.getX();
- mDraggingLabel = false;
- } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
- v.setBackgroundColor(0);
- if (mDraggingLabel) {
- Message msg = mLabelScroller.obtainMessage(0, tv);
- mLabelScroller.sendMessageDelayed(msg, 1000);
- }
- } else if (action == MotionEvent.ACTION_MOVE) {
- if (mDraggingLabel) {
- int scrollx = tv.getScrollX();
- int x = (int) event.getX();
- int delta = mLastX - x;
- if (delta != 0) {
- mLastX = x;
- scrollx += delta;
- if (scrollx > mTextWidth) {
- // scrolled the text completely off the view to the left
- scrollx -= mTextWidth;
- scrollx -= mViewWidth;
- }
- if (scrollx < -mViewWidth) {
- // scrolled the text completely off the view to the right
- scrollx += mViewWidth;
- scrollx += mTextWidth;
- }
- tv.scrollTo(scrollx, 0);
- }
- return true;
- }
- int delta = mInitialX - (int) event.getX();
- if (Math.abs(delta) > mTouchSlop) {
- // start moving
- mLabelScroller.removeMessages(0, tv);
-
- // Only turn ellipsizing off when it's not already off, because it
- // causes the scroll position to be reset to 0.
- if (tv.getEllipsize() != null) {
- tv.setEllipsize(null);
- }
- Layout ll = tv.getLayout();
- // layout might be null if the text just changed, or ellipsizing
- // was just turned off
- if (ll == null) {
- return false;
- }
- // get the non-ellipsized line width, to determine whether scrolling
- // should even be allowed
- mTextWidth = (int) tv.getLayout().getLineWidth(0);
- mViewWidth = tv.getWidth();
- if (mViewWidth > mTextWidth) {
- tv.setEllipsize(TruncateAt.END);
- v.cancelLongPress();
- return false;
- }
- mDraggingLabel = true;
- tv.setHorizontalFadingEdgeEnabled(true);
- v.cancelLongPress();
- return true;
- }
- }
- return false;
- }
-
- Handler mLabelScroller = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- TextView tv = (TextView) msg.obj;
- int x = tv.getScrollX();
- x = x * 3 / 4;
- tv.scrollTo(x, 0);
- if (x == 0) {
- tv.setEllipsize(TruncateAt.END);
- } else {
- Message newmsg = obtainMessage(0, tv);
- mLabelScroller.sendMessageDelayed(newmsg, 15);
- }
- }
- };
-
- public boolean onLongClick(View view) {
- CharSequence title = null;
- String mime = null;
- String query = null;
- if (getMediaController() == null) {
- LogHelper.d(TAG, "No media controller avalable yet");
- return true;
- }
- MediaMetadata metadata = getMediaController().getMetadata();
- if (metadata == null) {
- LogHelper.d(TAG, "No metadata avalable yet");
- return true;
- }
- String artist = metadata.getString(MediaMetadata.METADATA_KEY_ARTIST);
- String album = metadata.getString(MediaMetadata.METADATA_KEY_ALBUM);
- String song = metadata.getString(MediaMetadata.METADATA_KEY_TITLE);
- long audioid = metadata.getLong(MediaMetadata.METADATA_KEY_MEDIA_ID);
-
- if (album == null && artist == null && song != null && song.startsWith("recording")) {
- LogHelper.d(TAG, "Item is not music");
- return false;
- }
-
- if (audioid < 0) {
- return false;
- }
-
- boolean knownartist = (artist != null) && !MediaStore.UNKNOWN_STRING.equals(artist);
- boolean knownalbum = (album != null) && !MediaStore.UNKNOWN_STRING.equals(album);
-
- if (knownartist && view.equals(mArtistName.getParent())) {
- title = artist;
- query = artist;
- mime = MediaStore.Audio.Artists.ENTRY_CONTENT_TYPE;
- } else if (knownalbum && view.equals(mAlbumName.getParent())) {
- title = album;
- if (knownartist) {
- query = artist + " " + album;
- } else {
- query = album;
- }
- mime = MediaStore.Audio.Albums.ENTRY_CONTENT_TYPE;
- } else if (view.equals(mTrackName.getParent()) || !knownartist || !knownalbum) {
- if ((song == null) || MediaStore.UNKNOWN_STRING.equals(song)) {
- // A popup of the form "Search for null/'' using ..." is pretty
- // unhelpful, plus, we won't find any way to buy it anyway.
- return true;
- }
-
- title = song;
- if (knownartist) {
- query = artist + " " + song;
- } else {
- query = song;
- }
- mime = "audio/*"; // the specific type doesn't matter, so don't bother retrieving it
- } else {
- throw new RuntimeException("shouldn't be here");
- }
- title = getString(R.string.mediasearch, title);
-
- Intent i = new Intent();
- i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- i.setAction(MediaStore.INTENT_ACTION_MEDIA_SEARCH);
- i.putExtra(SearchManager.QUERY, query);
- if (knownartist) {
- i.putExtra(MediaStore.EXTRA_MEDIA_ARTIST, artist);
- }
- if (knownalbum) {
- i.putExtra(MediaStore.EXTRA_MEDIA_ALBUM, album);
- }
- i.putExtra(MediaStore.EXTRA_MEDIA_TITLE, song);
- i.putExtra(MediaStore.EXTRA_MEDIA_FOCUS, mime);
-
- startActivity(Intent.createChooser(i, title));
- return true;
- }
-
- @Override
- public void onStart() {
- LogHelper.d(TAG, "onStart()");
- super.onStart();
- mMediaBrowser.connect();
- }
-
- @Override
- public void onStop() {
- LogHelper.d(TAG, "onStop()");
- mMediaBrowser.disconnect();
- super.onStop();
- }
-
- @Override
- public void onResume() {
- LogHelper.d(TAG, "onResume()");
- super.onResume();
- updateTrackInfo();
- setPauseButtonImage();
- }
-
- @Override
- public void onDestroy() {
- LogHelper.d(TAG, "onDestroy()");
- super.onDestroy();
- }
-
- private void scanBackward(int repcnt, long delta) {
- if (getMediaController() == null) return;
- if (repcnt == 0) {
- mStartSeekPos = getMediaController().getPlaybackState().getPosition();
- mLastSeekEventTime = 0;
- } else {
- if (delta < 5000) {
- // seek at 10x speed for the first 5 seconds
- delta = delta * 10;
- } else {
- // seek at 40x after that
- delta = 50000 + (delta - 5000) * 40;
- }
- long newpos = mStartSeekPos - delta;
- if (newpos < 0) {
- // move to previous track
- getMediaController().getTransportControls().skipToPrevious();
- long duration = getMediaController().getMetadata().getLong(
- MediaMetadata.METADATA_KEY_DURATION);
- mStartSeekPos += duration;
- newpos += duration;
- }
- if (((delta - mLastSeekEventTime) > 250) || repcnt < 0) {
- getMediaController().getTransportControls().seekTo(newpos);
- mLastSeekEventTime = delta;
- }
- updateProgressBar();
- }
- }
-
- private void scanForward(int repcnt, long delta) {
- if (getMediaController() == null) return;
- if (repcnt == 0) {
- mStartSeekPos = getMediaController().getPlaybackState().getPosition();
- mLastSeekEventTime = 0;
- } else {
- if (delta < 5000) {
- // seek at 10x speed for the first 5 seconds
- delta = delta * 10;
- } else {
- // seek at 40x after that
- delta = 50000 + (delta - 5000) * 40;
- }
- long newpos = mStartSeekPos + delta;
- long duration =
- getMediaController().getMetadata().getLong(MediaMetadata.METADATA_KEY_DURATION);
- if (newpos >= duration) {
- // move to next track
- getMediaController().getTransportControls().skipToNext();
- mStartSeekPos -= duration; // is OK to go negative
- newpos -= duration;
- }
- if (((delta - mLastSeekEventTime) > 250) || repcnt < 0) {
- getMediaController().getTransportControls().seekTo(newpos);
- mLastSeekEventTime = delta;
- }
- updateProgressBar();
- }
- }
-
- private void toggleShuffle() {
- // TODO(b/36371715): Implement shuffle for SHUFFLE_NORMAL, SHUFFLE_AUTO, SHUFFLE_NONE
- LogHelper.d(TAG, "Shuffle not implemented yet");
- Toast.makeText(this, "Shuffle not implemented yet", Toast.LENGTH_SHORT).show();
- }
-
- private void setRepeatMode(MediaPlaybackService.RepeatMode repeatMode) {
- Bundle extras = new Bundle();
- extras.putInt(MediaPlaybackService.REPEAT_MODE, repeatMode.ordinal());
- getMediaController().getTransportControls().sendCustomAction(
- MediaPlaybackService.CMD_REPEAT, extras);
- }
-
- private void setRepeatButtonImage(MediaPlaybackService.RepeatMode repeatMode) {
- if (getMediaController() == null) return;
- Bundle extras = getMediaController().getExtras();
- if (extras == null) return;
- if (repeatMode == null) {
- repeatMode = MediaPlaybackService.RepeatMode
- .values()[extras.getInt(MediaPlaybackService.REPEAT_MODE)];
- }
- switch (repeatMode) {
- case REPEAT_CURRENT:
- mRepeatButton.setImageResource(R.drawable.ic_mp_repeat_once_btn);
- break;
- case REPEAT_ALL:
- mRepeatButton.setImageResource(R.drawable.ic_mp_repeat_all_btn);
- break;
- case REPEAT_NONE:
- default:
- mRepeatButton.setImageResource(R.drawable.ic_mp_repeat_off_btn);
- break;
- }
- }
-
- private void showToast(int resid) {
- if (mToast == null) {
- mToast = Toast.makeText(this, "", Toast.LENGTH_SHORT);
- }
- mToast.setText(resid);
- mToast.show();
- }
-
- private void setShuffleButtonImage() {
- if (getMediaController() == null) return;
- mShuffleButton.setImageResource(R.drawable.ic_mp_shuffle_off_btn);
- }
-
- private void setPauseButtonImage() {
- if (getMediaController() == null) {
- return;
- }
- if (getMediaController().getPlaybackState().getState() != PlaybackState.STATE_PLAYING) {
- mPlayPauseButton.setImageResource(android.R.drawable.ic_media_play);
- } else {
- mPlayPauseButton.setImageResource(android.R.drawable.ic_media_pause);
- }
- }
-
- private long updateProgressBar() {
- MediaController mediaController = getMediaController();
- if (mediaController == null || mediaController.getMetadata() == null
- || mediaController.getPlaybackState() == null) {
- return 500;
- }
- long duration = mediaController.getMetadata().getLong(MediaMetadata.METADATA_KEY_DURATION);
- long pos = mediaController.getPlaybackState().getPosition();
- if ((pos >= 0) && (duration > 0)) {
- mCurrentTime.setText(MusicUtils.makeTimeString(this, pos / 1000));
- int progress = (int) (1000 * pos / duration);
- mProgress.setProgress(progress);
-
- if (mediaController.getPlaybackState().getState() == PlaybackState.STATE_PLAYING) {
- mCurrentTime.setVisibility(View.VISIBLE);
- } else {
- // blink the counter
- int vis = mCurrentTime.getVisibility();
- mCurrentTime.setVisibility(vis == View.INVISIBLE ? View.VISIBLE : View.INVISIBLE);
- return 500;
- }
- } else {
- mCurrentTime.setText("--:--");
- mProgress.setProgress(1000);
- }
- // calculate the number of milliseconds until the next full second, so
- // the counter can be updated at just the right time
- long remaining = 1000 - (pos % 1000);
-
- // approximate how often we would need to refresh the slider to
- // move it smoothly
- int width = mProgress.getWidth();
- if (width == 0) width = 320;
- long smoothrefreshtime = duration / width;
-
- if (smoothrefreshtime > remaining) return remaining;
- if (smoothrefreshtime < 20) return 20;
- return smoothrefreshtime;
- }
-
- private void updateTrackInfo() {
- LogHelper.d(TAG, "updateTrackInfo()");
- if (getMediaController() == null) {
- return;
- }
- MediaMetadata metadata = getMediaController().getMetadata();
- if (metadata == null) {
- return;
- }
- mTrackInfo.setVisibility(View.VISIBLE);
- mTrackName.setText(metadata.getString(MediaMetadata.METADATA_KEY_TITLE));
- LogHelper.d(TAG, "Track Name: ", mTrackName.getText());
- String artistName = metadata.getString(MediaMetadata.METADATA_KEY_ARTIST);
- if (artistName.equals(MusicProvider.UNKOWN)) {
- artistName = getString(R.string.unknown_artist_name);
- }
- mArtistName.setText(artistName);
- String albumName = metadata.getString(MediaMetadata.METADATA_KEY_ALBUM);
- if (albumName.equals(MusicProvider.UNKOWN)) {
- albumName = getString(R.string.unknown_album_name);
- }
- mAlbumName.setText(albumName);
- Bitmap albumArt = metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
- if (albumArt != null) {
- mAlbumArt.setImageBitmap(albumArt);
- } else {
- mAlbumArt.setImageDrawable(mDefaultAlbumArt);
- }
- mAlbumArt.setVisibility(View.VISIBLE);
-
- long duration = metadata.getLong(MediaMetadata.METADATA_KEY_DURATION);
- mTotalTime.setText(MusicUtils.makeTimeString(this, duration / 1000));
- }
-}
diff --git a/src/com/android/music/MediaPlaybackService.java b/src/com/android/music/MediaPlaybackService.java
index 70d4f4b..255b52b 100644
--- a/src/com/android/music/MediaPlaybackService.java
+++ b/src/com/android/music/MediaPlaybackService.java
@@ -19,77 +19,30 @@
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
-import android.graphics.Bitmap;
-import android.media.MediaDescription;
-import android.media.MediaMetadata;
import android.media.browse.MediaBrowser.MediaItem;
import android.media.session.MediaSession;
import android.media.session.PlaybackState;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.SystemClock;
import android.service.media.MediaBrowserService;
-import android.text.TextUtils;
import android.util.Log;
-import com.android.music.utils.*;
-import java.lang.ref.WeakReference;
import java.util.*;
-import static com.android.music.utils.MediaIDHelper.*;
-
/**
* Provides "background" audio playback capabilities, allowing the
* user to switch between activities without stopping playback.
*/
-public class MediaPlaybackService extends MediaBrowserService implements Playback.Callback {
- private static final String TAG = LogHelper.makeLogTag(MediaPlaybackService.class);
-
- // Delay stopSelf by using a handler.
- private static final int STOP_DELAY = 30000;
-
- public static final String ACTION_CMD = "com.android.music.ACTION_CMD";
- public static final String CMD_NAME = "CMD_NAME";
- public static final String CMD_PAUSE = "CMD_PAUSE";
- public static final String CMD_REPEAT = "CMD_PAUSE";
- public static final String REPEAT_MODE = "REPEAT_MODE";
-
- public enum RepeatMode { REPEAT_NONE, REPEAT_ALL, REPEAT_CURRENT }
-
- // Music catalog manager
- private MusicProvider mMusicProvider;
+public class MediaPlaybackService extends MediaBrowserService {
private MediaSession mSession;
- // "Now playing" queue:
- private List<MediaSession.QueueItem> mPlayingQueue = null;
- private int mCurrentIndexOnQueue = -1;
- private MediaNotificationManager mMediaNotificationManager;
- // Indicates whether the service was started.
- private boolean mServiceStarted;
- private DelayedStopHandler mDelayedStopHandler = new DelayedStopHandler(this);
- private Playback mPlayback;
- // Default mode is repeat none
- private RepeatMode mRepeatMode = RepeatMode.REPEAT_NONE;
- // Extra information for this session
- private Bundle mExtras;
public MediaPlaybackService() {}
@Override
public void onCreate() {
- LogHelper.d(TAG, "onCreate()");
super.onCreate();
- LogHelper.d(TAG, "Create MusicProvider");
- mPlayingQueue = new ArrayList<>();
- mMusicProvider = new MusicProvider(this);
- LogHelper.d(TAG, "Create MediaSession");
// Start a new MediaSession
mSession = new MediaSession(this, "MediaPlaybackService");
- // Set extra information
- mExtras = new Bundle();
- mExtras.putInt(REPEAT_MODE, mRepeatMode.ordinal());
- mSession.setExtras(mExtras);
// Enable callbacks from MediaButtons and TransportControls
mSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS
| MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
@@ -97,659 +50,63 @@
PlaybackState.Builder stateBuilder = new PlaybackState.Builder().setActions(
PlaybackState.ACTION_PLAY | PlaybackState.ACTION_PLAY_PAUSE);
mSession.setPlaybackState(stateBuilder.build());
- // MediaSessionCallback() has methods that handle callbacks from a media controller
- mSession.setCallback(new MediaSessionCallback());
- // Set the session's token so that client activities can communicate with it.
setSessionToken(mSession.getSessionToken());
- mPlayback = new Playback(this, mMusicProvider);
- mPlayback.setState(PlaybackState.STATE_NONE);
- mPlayback.setCallback(this);
- mPlayback.start();
-
Context context = getApplicationContext();
Intent intent = new Intent(context, MusicBrowserActivity.class);
PendingIntent pi = PendingIntent.getActivity(
context, 99 /*request code*/, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mSession.setSessionActivity(pi);
-
- updatePlaybackState(null);
-
- mMediaNotificationManager = new MediaNotificationManager(this);
}
@Override
public int onStartCommand(Intent startIntent, int flags, int startId) {
- if (startIntent != null) {
- String action = startIntent.getAction();
- String command = startIntent.getStringExtra(CMD_NAME);
- if (ACTION_CMD.equals(action)) {
- if (CMD_PAUSE.equals(command)) {
- if (mPlayback != null && mPlayback.isPlaying()) {
- handlePauseRequest();
- }
- }
- }
- }
return START_STICKY;
}
@Override
- public void onDestroy() {
- Log.d(TAG, "onDestroy");
- // Service is being killed, so make sure we release our resources
- handleStopRequest(null);
-
- mDelayedStopHandler.removeCallbacksAndMessages(null);
- // Always release the MediaSession to clean up resources
- // and notify associated MediaController(s).
- mSession.release();
- }
+ public void onDestroy() {}
@Override
public BrowserRoot onGetRoot(String clientPackageName, int clientUid, Bundle rootHints) {
- Log.d(TAG,
- "OnGetRoot: clientPackageName=" + clientPackageName + "; clientUid=" + clientUid
- + " ; rootHints=" + rootHints);
- // Allow everyone to browse
- return new BrowserRoot(MEDIA_ID_ROOT, null);
+ return null;
}
@Override
public void onLoadChildren(final String parentMediaId, final Result<List<MediaItem>> result) {
- Log.d(TAG, "OnLoadChildren: parentMediaId=" + parentMediaId);
- // Browsing not allowed
- if (parentMediaId == null) {
- result.sendResult(null);
- return;
- }
- if (!mMusicProvider.isInitialized()) {
- // Use result.detach to allow calling result.sendResult from another thread:
- result.detach();
-
- mMusicProvider.retrieveMediaAsync(new MusicProvider.MusicProviderCallback() {
- @Override
- public void onMusicCatalogReady(boolean success) {
- Log.d(TAG, "Received catalog result, success: " + String.valueOf(success));
- if (success) {
- onLoadChildren(parentMediaId, result);
- } else {
- result.sendResult(Collections.emptyList());
- }
- }
- });
-
- } else {
- // If our music catalog is already loaded/cached, load them into result immediately
- List<MediaItem> mediaItems = new ArrayList<>();
-
- switch (parentMediaId) {
- case MEDIA_ID_ROOT:
- Log.d(TAG, "OnLoadChildren.ROOT");
- mediaItems.add(new MediaItem(new MediaDescription.Builder()
- .setMediaId(MEDIA_ID_MUSICS_BY_ARTIST)
- .setTitle("Artists")
- .build(),
- MediaItem.FLAG_BROWSABLE));
- mediaItems.add(new MediaItem(new MediaDescription.Builder()
- .setMediaId(MEDIA_ID_MUSICS_BY_ALBUM)
- .setTitle("Albums")
- .build(),
- MediaItem.FLAG_BROWSABLE));
- mediaItems.add(new MediaItem(new MediaDescription.Builder()
- .setMediaId(MEDIA_ID_MUSICS_BY_SONG)
- .setTitle("Songs")
- .build(),
- MediaItem.FLAG_BROWSABLE));
- mediaItems.add(new MediaItem(new MediaDescription.Builder()
- .setMediaId(MEDIA_ID_MUSICS_BY_PLAYLIST)
- .setTitle("Playlists")
- .build(),
- MediaItem.FLAG_BROWSABLE));
- break;
- case MEDIA_ID_MUSICS_BY_ARTIST:
- Log.d(TAG, "OnLoadChildren.ARTIST");
- for (String artist : mMusicProvider.getArtists()) {
- MediaItem item = new MediaItem(
- new MediaDescription.Builder()
- .setMediaId(MediaIDHelper.createBrowseCategoryMediaID(
- MEDIA_ID_MUSICS_BY_ARTIST, artist))
- .setTitle(artist)
- .build(),
- MediaItem.FLAG_BROWSABLE);
- mediaItems.add(item);
- }
- break;
- case MEDIA_ID_MUSICS_BY_PLAYLIST:
- LogHelper.d(TAG, "OnLoadChildren.PLAYLIST");
- for (String playlist : mMusicProvider.getPlaylists()) {
- MediaItem item = new MediaItem(
- new MediaDescription.Builder()
- .setMediaId(MediaIDHelper.createBrowseCategoryMediaID(
- MEDIA_ID_MUSICS_BY_PLAYLIST, playlist))
- .setTitle(playlist)
- .build(),
- MediaItem.FLAG_BROWSABLE);
- mediaItems.add(item);
- }
- break;
- case MEDIA_ID_MUSICS_BY_ALBUM:
- Log.d(TAG, "OnLoadChildren.ALBUM");
- loadAlbum(mMusicProvider.getAlbums(), mediaItems);
- break;
- case MEDIA_ID_MUSICS_BY_SONG:
- Log.d(TAG, "OnLoadChildren.SONG");
- String hierarchyAwareMediaID = MediaIDHelper.createBrowseCategoryMediaID(
- parentMediaId, MEDIA_ID_MUSICS_BY_SONG);
- loadSong(mMusicProvider.getMusicList(), mediaItems, hierarchyAwareMediaID);
- break;
- default:
- if (parentMediaId.startsWith(MEDIA_ID_MUSICS_BY_ARTIST)) {
- String artist = MediaIDHelper.getHierarchy(parentMediaId)[1];
- Log.d(TAG, "OnLoadChildren.SONGS_BY_ARTIST artist=" + artist);
- loadAlbum(mMusicProvider.getAlbumByArtist(artist), mediaItems);
- } else if (parentMediaId.startsWith(MEDIA_ID_MUSICS_BY_ALBUM)) {
- String album = MediaIDHelper.getHierarchy(parentMediaId)[1];
- Log.d(TAG, "OnLoadChildren.SONGS_BY_ALBUM album=" + album);
- loadSong(mMusicProvider.getMusicsByAlbum(album), mediaItems, parentMediaId);
- } else if (parentMediaId.startsWith(MEDIA_ID_MUSICS_BY_PLAYLIST)) {
- String playlist = MediaIDHelper.getHierarchy(parentMediaId)[1];
- LogHelper.d(TAG, "OnLoadChildren.SONGS_BY_PLAYLIST playlist=", playlist);
- if (playlist.equals(MEDIA_ID_NOW_PLAYING) && mPlayingQueue != null
- && mPlayingQueue.size() > 0) {
- loadPlayingQueue(mediaItems, parentMediaId);
- } else {
- loadSong(mMusicProvider.getMusicsByPlaylist(playlist), mediaItems,
- parentMediaId);
- }
- } else {
- Log.w(TAG, "Skipping unmatched parentMediaId: " + parentMediaId);
- }
- break;
- }
- Log.d(TAG,
- "OnLoadChildren sending " + mediaItems.size() + " results for "
- + parentMediaId);
- result.sendResult(mediaItems);
- }
- }
-
- private void loadPlayingQueue(List<MediaItem> mediaItems, String parentId) {
- for (MediaSession.QueueItem queueItem : mPlayingQueue) {
- MediaItem mediaItem =
- new MediaItem(queueItem.getDescription(), MediaItem.FLAG_PLAYABLE);
- mediaItems.add(mediaItem);
- }
- }
-
- private void loadSong(
- Iterable<MediaMetadata> songList, List<MediaItem> mediaItems, String parentId) {
- for (MediaMetadata metadata : songList) {
- String hierarchyAwareMediaID =
- MediaIDHelper.createMediaID(metadata.getDescription().getMediaId(), parentId);
- Bundle songExtra = new Bundle();
- songExtra.putLong(MediaMetadata.METADATA_KEY_DURATION,
- metadata.getLong(MediaMetadata.METADATA_KEY_DURATION));
- String title = metadata.getString(MediaMetadata.METADATA_KEY_TITLE);
- String artistName = metadata.getString(MediaMetadata.METADATA_KEY_ARTIST);
- MediaItem item = new MediaItem(new MediaDescription.Builder()
- .setMediaId(hierarchyAwareMediaID)
- .setTitle(title)
- .setSubtitle(artistName)
- .setExtras(songExtra)
- .build(),
- MediaItem.FLAG_PLAYABLE);
- mediaItems.add(item);
- }
- }
-
- private void loadAlbum(Iterable<MediaMetadata> albumList, List<MediaItem> mediaItems) {
- for (MediaMetadata albumMetadata : albumList) {
- String albumName = albumMetadata.getString(MediaMetadata.METADATA_KEY_ALBUM);
- String artistName = albumMetadata.getString(MediaMetadata.METADATA_KEY_ARTIST);
- Bundle albumExtra = new Bundle();
- albumExtra.putLong(MediaMetadata.METADATA_KEY_NUM_TRACKS,
- albumMetadata.getLong(MediaMetadata.METADATA_KEY_NUM_TRACKS));
- MediaItem item = new MediaItem(
- new MediaDescription.Builder()
- .setMediaId(MediaIDHelper.createBrowseCategoryMediaID(
- MEDIA_ID_MUSICS_BY_ALBUM, albumName))
- .setTitle(albumName)
- .setSubtitle(artistName)
- .setIconBitmap(
- albumMetadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART))
- .setExtras(albumExtra)
- .build(),
- MediaItem.FLAG_BROWSABLE);
- mediaItems.add(item);
- }
+ result.sendResult(null);
+ return;
}
private final class MediaSessionCallback extends MediaSession.Callback {
@Override
- public void onPlay() {
- Log.d(TAG, "play");
-
- if (mPlayingQueue == null || mPlayingQueue.isEmpty()) {
- mPlayingQueue = QueueHelper.getRandomQueue(mMusicProvider);
- mSession.setQueue(mPlayingQueue);
- mSession.setQueueTitle(getString(R.string.random_queue_title));
- // start playing from the beginning of the queue
- mCurrentIndexOnQueue = 0;
- }
-
- if (mPlayingQueue != null && !mPlayingQueue.isEmpty()) {
- handlePlayRequest();
- }
- }
+ public void onPlay() {}
@Override
- public void onSkipToQueueItem(long queueId) {
- LogHelper.d(TAG, "OnSkipToQueueItem:", queueId);
-
- if (mPlayingQueue != null && !mPlayingQueue.isEmpty()) {
- // set the current index on queue from the music Id:
- mCurrentIndexOnQueue = QueueHelper.getMusicIndexOnQueue(mPlayingQueue, queueId);
- // play the music
- handlePlayRequest();
- }
- }
+ public void onSkipToQueueItem(long queueId) {}
@Override
- public void onSeekTo(long position) {
- Log.d(TAG, "onSeekTo:" + position);
- mPlayback.seekTo((int) position);
- }
+ public void onSeekTo(long position) {}
@Override
- public void onPlayFromMediaId(String mediaId, Bundle extras) {
- LogHelper.d(TAG, "playFromMediaId mediaId:", mediaId, " extras=", extras);
-
- // The mediaId used here is not the unique musicId. This one comes from the
- // MediaBrowser, and is actually a "hierarchy-aware mediaID": a concatenation of
- // the hierarchy in MediaBrowser and the actual unique musicID. This is necessary
- // so we can build the correct playing queue, based on where the track was
- // selected from.
- mPlayingQueue = QueueHelper.getPlayingQueue(mediaId, mMusicProvider);
- mSession.setQueue(mPlayingQueue);
- String queueTitle = getString(R.string.browse_musics_by_genre_subtitle,
- MediaIDHelper.extractBrowseCategoryValueFromMediaID(mediaId));
- mSession.setQueueTitle(queueTitle);
-
- if (mPlayingQueue != null && !mPlayingQueue.isEmpty()) {
- // set the current index on queue from the media Id:
- mCurrentIndexOnQueue = QueueHelper.getMusicIndexOnQueue(mPlayingQueue, mediaId);
-
- if (mCurrentIndexOnQueue < 0) {
- LogHelper.e(TAG, "playFromMediaId: media ID ", mediaId,
- " could not be found on queue. Ignoring.");
- } else {
- // play the music
- handlePlayRequest();
- }
- }
- }
+ public void onPlayFromMediaId(String mediaId, Bundle extras) {}
@Override
- public void onPause() {
- LogHelper.d(TAG, "pause. current state=" + mPlayback.getState());
- handlePauseRequest();
- }
+ public void onPause() {}
@Override
- public void onStop() {
- LogHelper.d(TAG, "stop. current state=" + mPlayback.getState());
- handleStopRequest(null);
- }
+ public void onStop() {}
@Override
- public void onSkipToNext() {
- LogHelper.d(TAG, "skipToNext");
- mCurrentIndexOnQueue++;
- if (mPlayingQueue != null && mCurrentIndexOnQueue >= mPlayingQueue.size()) {
- // This sample's behavior: skipping to next when in last song returns to the
- // first song.
- mCurrentIndexOnQueue = 0;
- }
- if (QueueHelper.isIndexPlayable(mCurrentIndexOnQueue, mPlayingQueue)) {
- handlePlayRequest();
- } else {
- LogHelper.e(TAG,
- "skipToNext: cannot skip to next. next Index=" + mCurrentIndexOnQueue
- + " queue length="
- + (mPlayingQueue == null ? "null" : mPlayingQueue.size()));
- handleStopRequest("Cannot skip");
- }
- }
+ public void onSkipToNext() {}
@Override
- public void onSkipToPrevious() {
- LogHelper.d(TAG, "skipToPrevious");
- mCurrentIndexOnQueue--;
- if (mPlayingQueue != null && mCurrentIndexOnQueue < 0) {
- // This sample's behavior: skipping to previous when in first song restarts the
- // first song.
- mCurrentIndexOnQueue = 0;
- }
- if (QueueHelper.isIndexPlayable(mCurrentIndexOnQueue, mPlayingQueue)) {
- handlePlayRequest();
- } else {
- LogHelper.e(TAG,
- "skipToPrevious: cannot skip to previous. previous Index="
- + mCurrentIndexOnQueue + " queue length="
- + (mPlayingQueue == null ? "null" : mPlayingQueue.size()));
- handleStopRequest("Cannot skip");
- }
- }
+ public void onSkipToPrevious() {}
@Override
- public void onPlayFromSearch(String query, Bundle extras) {
- LogHelper.d(TAG, "playFromSearch query=", query);
-
- if (TextUtils.isEmpty(query)) {
- // A generic search like "Play music" sends an empty query
- // and it's expected that we start playing something. What will be played depends
- // on the app: favorite playlist, "I'm feeling lucky", most recent, etc.
- mPlayingQueue = QueueHelper.getRandomQueue(mMusicProvider);
- } else {
- mPlayingQueue = QueueHelper.getPlayingQueueFromSearch(query, mMusicProvider);
- }
-
- LogHelper.d(TAG, "playFromSearch playqueue.length=" + mPlayingQueue.size());
- mSession.setQueue(mPlayingQueue);
-
- if (mPlayingQueue != null && !mPlayingQueue.isEmpty()) {
- // immediately start playing from the beginning of the search results
- mCurrentIndexOnQueue = 0;
-
- handlePlayRequest();
- } else {
- // if nothing was found, we need to warn the user and stop playing
- handleStopRequest(getString(R.string.no_search_results));
- }
- }
+ public void onPlayFromSearch(String query, Bundle extras) {}
@Override
- public void onCustomAction(String action, Bundle extras) {
- LogHelper.d(TAG, "onCustomAction action=", action, ", extras=", extras);
- switch (action) {
- case CMD_REPEAT:
- mRepeatMode = RepeatMode.values()[extras.getInt(REPEAT_MODE)];
- mExtras.putInt(REPEAT_MODE, mRepeatMode.ordinal());
- mSession.setExtras(mExtras);
- LogHelper.d(TAG, "modified repeatMode=", mRepeatMode);
- break;
- default:
- LogHelper.d(TAG, "Unkown action=", action);
- break;
- }
- }
- }
-
- /**
- * Handle a request to play music
- */
- private void handlePlayRequest() {
- LogHelper.d(TAG, "handlePlayRequest: mState=" + mPlayback.getState());
-
- mDelayedStopHandler.removeCallbacksAndMessages(null);
- if (!mServiceStarted) {
- LogHelper.v(TAG, "Starting service");
- // The MusicService needs to keep running even after the calling MediaBrowser
- // is disconnected. Call startService(Intent) and then stopSelf(..) when we no longer
- // need to play media.
- startService(new Intent(getApplicationContext(), MediaPlaybackService.class));
- mServiceStarted = true;
- }
-
- if (!mSession.isActive()) {
- mSession.setActive(true);
- }
-
- if (QueueHelper.isIndexPlayable(mCurrentIndexOnQueue, mPlayingQueue)) {
- updateMetadata();
- mPlayback.play(mPlayingQueue.get(mCurrentIndexOnQueue));
- }
- }
-
- /**
- * Handle a request to pause music
- */
- private void handlePauseRequest() {
- LogHelper.d(TAG, "handlePauseRequest: mState=" + mPlayback.getState());
- mPlayback.pause();
- // reset the delayed stop handler.
- mDelayedStopHandler.removeCallbacksAndMessages(null);
- mDelayedStopHandler.sendEmptyMessageDelayed(0, STOP_DELAY);
- }
-
- /**
- * Handle a request to stop music
- */
- private void handleStopRequest(String withError) {
- LogHelper.d(
- TAG, "handleStopRequest: mState=" + mPlayback.getState() + " error=", withError);
- mPlayback.stop(true);
- // reset the delayed stop handler.
- mDelayedStopHandler.removeCallbacksAndMessages(null);
- mDelayedStopHandler.sendEmptyMessageDelayed(0, STOP_DELAY);
-
- updatePlaybackState(withError);
-
- // service is no longer necessary. Will be started again if needed.
- stopSelf();
- mServiceStarted = false;
- }
-
- private void updateMetadata() {
- if (!QueueHelper.isIndexPlayable(mCurrentIndexOnQueue, mPlayingQueue)) {
- LogHelper.e(TAG, "Can't retrieve current metadata.");
- updatePlaybackState(getResources().getString(R.string.error_no_metadata));
- return;
- }
- MediaSession.QueueItem queueItem = mPlayingQueue.get(mCurrentIndexOnQueue);
- String musicId =
- MediaIDHelper.extractMusicIDFromMediaID(queueItem.getDescription().getMediaId());
- MediaMetadata track = mMusicProvider.getMusicByMediaId(musicId).getMetadata();
- final String trackId = track.getString(MediaMetadata.METADATA_KEY_MEDIA_ID);
- if (!musicId.equals(trackId)) {
- IllegalStateException e = new IllegalStateException("track ID should match musicId.");
- LogHelper.e(TAG, "track ID should match musicId.", " musicId=", musicId,
- " trackId=", trackId,
- " mediaId from queueItem=", queueItem.getDescription().getMediaId(),
- " title from queueItem=", queueItem.getDescription().getTitle(),
- " mediaId from track=", track.getDescription().getMediaId(),
- " title from track=", track.getDescription().getTitle(),
- " source.hashcode from track=",
- track.getString(MusicProvider.CUSTOM_METADATA_TRACK_SOURCE).hashCode(), e);
- throw e;
- }
- LogHelper.d(TAG, "Updating metadata for MusicID= " + musicId);
- mSession.setMetadata(track);
-
- // Set the proper album artwork on the media session, so it can be shown in the
- // locked screen and in other places.
- if (track.getDescription().getIconBitmap() == null
- && track.getDescription().getIconUri() != null) {
- String albumUri = track.getDescription().getIconUri().toString();
- AlbumArtCache.getInstance().fetch(albumUri, new AlbumArtCache.FetchListener() {
- @Override
- public void onFetched(String artUrl, Bitmap bitmap, Bitmap icon) {
- MediaSession.QueueItem queueItem = mPlayingQueue.get(mCurrentIndexOnQueue);
- MediaMetadata track = mMusicProvider.getMusicByMediaId(trackId).getMetadata();
- track = new MediaMetadata
- .Builder(track)
-
- // set high resolution bitmap in METADATA_KEY_ALBUM_ART. This is
- // used, for
- // example, on the lockscreen background when the media session
- // is active.
- .putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, bitmap)
-
- // set small version of the album art in the DISPLAY_ICON. This
- // is used on
- // the MediaDescription and thus it should be small to be
- // serialized if
- // necessary..
- .putBitmap(MediaMetadata.METADATA_KEY_DISPLAY_ICON, icon)
-
- .build();
-
- mMusicProvider.updateMusic(trackId, track);
-
- // If we are still playing the same music
- String currentPlayingId = MediaIDHelper.extractMusicIDFromMediaID(
- queueItem.getDescription().getMediaId());
- if (trackId.equals(currentPlayingId)) {
- mSession.setMetadata(track);
- }
- }
- });
- }
- }
-
- /**
- * Update the current media player state, optionally showing an error message.
- *
- * @param error if not null, error message to present to the user.
- */
- private void updatePlaybackState(String error) {
- LogHelper.d(TAG, "updatePlaybackState, playback state=" + mPlayback.getState());
- long position = PlaybackState.PLAYBACK_POSITION_UNKNOWN;
- if (mPlayback != null && mPlayback.isConnected()) {
- position = mPlayback.getCurrentStreamPosition();
- }
-
- PlaybackState.Builder stateBuilder =
- new PlaybackState.Builder().setActions(getAvailableActions());
-
- int state = mPlayback.getState();
-
- // If there is an error message, send it to the playback state:
- if (error != null) {
- // Error states are really only supposed to be used for errors that cause playback to
- // stop unexpectedly and persist until the user takes action to fix it.
- stateBuilder.setErrorMessage(error);
- state = PlaybackState.STATE_ERROR;
- }
- stateBuilder.setState(state, position, 1.0f, SystemClock.elapsedRealtime());
-
- // Set the activeQueueItemId if the current index is valid.
- if (QueueHelper.isIndexPlayable(mCurrentIndexOnQueue, mPlayingQueue)) {
- MediaSession.QueueItem item = mPlayingQueue.get(mCurrentIndexOnQueue);
- stateBuilder.setActiveQueueItemId(item.getQueueId());
- }
-
- mSession.setPlaybackState(stateBuilder.build());
-
- if (state == PlaybackState.STATE_PLAYING || state == PlaybackState.STATE_PAUSED) {
- mMediaNotificationManager.startNotification();
- }
- }
-
- private long getAvailableActions() {
- long actions = PlaybackState.ACTION_PLAY | PlaybackState.ACTION_PLAY_FROM_MEDIA_ID
- | PlaybackState.ACTION_PLAY_FROM_SEARCH;
- if (mPlayingQueue == null || mPlayingQueue.isEmpty()) {
- return actions;
- }
- if (mPlayback.isPlaying()) {
- actions |= PlaybackState.ACTION_PAUSE;
- }
- if (mCurrentIndexOnQueue > 0) {
- actions |= PlaybackState.ACTION_SKIP_TO_PREVIOUS;
- }
- if (mCurrentIndexOnQueue < mPlayingQueue.size() - 1) {
- actions |= PlaybackState.ACTION_SKIP_TO_NEXT;
- }
- return actions;
- }
-
- private MediaMetadata getCurrentPlayingMusic() {
- if (QueueHelper.isIndexPlayable(mCurrentIndexOnQueue, mPlayingQueue)) {
- MediaSession.QueueItem item = mPlayingQueue.get(mCurrentIndexOnQueue);
- if (item != null) {
- LogHelper.d(TAG,
- "getCurrentPlayingMusic for musicId=", item.getDescription().getMediaId());
- return mMusicProvider
- .getMusicByMediaId(MediaIDHelper.extractMusicIDFromMediaID(
- item.getDescription().getMediaId()))
- .getMetadata();
- }
- }
- return null;
- }
-
- /**
- * Implementation of the Playback.Callback interface
- */
- @Override
- public void onCompletion() {
- // The media player finished playing the current song, so we go ahead
- // and start the next.
- if (mPlayingQueue != null && !mPlayingQueue.isEmpty()) {
- switch (mRepeatMode) {
- case REPEAT_ALL:
- // Increase the index
- mCurrentIndexOnQueue++;
- // Restart queue when reaching the end
- if (mCurrentIndexOnQueue >= mPlayingQueue.size()) {
- mCurrentIndexOnQueue = 0;
- }
- break;
- case REPEAT_CURRENT:
- // Do not change the index
- break;
- case REPEAT_NONE:
- default:
- // Increase the index
- mCurrentIndexOnQueue++;
- // Stop the queue when reaching the end
- if (mCurrentIndexOnQueue >= mPlayingQueue.size()) {
- handleStopRequest(null);
- return;
- }
- break;
- }
- handlePlayRequest();
- } else {
- // If there is nothing to play, we stop and release the resources:
- handleStopRequest(null);
- }
- }
-
- @Override
- public void onPlaybackStatusChanged(int state) {
- updatePlaybackState(null);
- }
-
- @Override
- public void onError(String error) {
- updatePlaybackState(error);
- }
-
- /**
- * A simple handler that stops the service if playback is not active (playing)
- */
- private static class DelayedStopHandler extends Handler {
- private final WeakReference<MediaPlaybackService> mWeakReference;
-
- private DelayedStopHandler(MediaPlaybackService service) {
- mWeakReference = new WeakReference<>(service);
- }
-
- @Override
- public void handleMessage(Message msg) {
- MediaPlaybackService service = mWeakReference.get();
- if (service != null && service.mPlayback != null) {
- if (service.mPlayback.isPlaying()) {
- Log.d(TAG, "Ignoring delayed stop since the media player is in use.");
- return;
- }
- Log.d(TAG, "Stopping service with delay handler.");
- service.stopSelf();
- service.mServiceStarted = false;
- }
- }
+ public void onCustomAction(String action, Bundle extras) {}
}
}
diff --git a/src/com/android/music/MusicAlphabetIndexer.java b/src/com/android/music/MusicAlphabetIndexer.java
deleted file mode 100644
index 8e84a72..0000000
--- a/src/com/android/music/MusicAlphabetIndexer.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music;
-
-import android.database.Cursor;
-import android.provider.MediaStore;
-import android.widget.AlphabetIndexer;
-
-/**
- * Handles comparisons in a different way because the Album, Song and Artist name
- * are stripped of some prefixes such as "a", "an", "the" and some symbols.
- *
- */
-class MusicAlphabetIndexer extends AlphabetIndexer {
- public MusicAlphabetIndexer(Cursor cursor, int sortedColumnIndex, CharSequence alphabet) {
- super(cursor, sortedColumnIndex, alphabet);
- }
-
- @Override
- protected int compare(String word, String letter) {
- String wordKey = MediaStore.Audio.keyFor(word);
- String letterKey = MediaStore.Audio.keyFor(letter);
- if (wordKey.startsWith(letter)) {
- return 0;
- } else {
- return wordKey.compareTo(letterKey);
- }
- }
-}
diff --git a/src/com/android/music/MusicBrowserActivity.java b/src/com/android/music/MusicBrowserActivity.java
index b6b30e8..ca9615e 100644
--- a/src/com/android/music/MusicBrowserActivity.java
+++ b/src/com/android/music/MusicBrowserActivity.java
@@ -16,63 +16,22 @@
package com.android.music;
-import android.Manifest.permission;
import android.app.Activity;
-import android.content.pm.PackageManager;
import android.os.Bundle;
-import com.android.music.utils.LogHelper;
+/**
+ * A skeleton class that provides empty implementations for Activity class.
+ */
public class MusicBrowserActivity extends Activity {
- private static final String TAG = LogHelper.makeLogTag(MusicBrowserActivity.class);
-
- private static final int MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 42;
-
public MusicBrowserActivity() {}
- /**
- * Called when the activity is first created.
- */
@Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- LogHelper.d(TAG, "onCreate()");
- if (checkSelfPermission(permission.READ_EXTERNAL_STORAGE)
- != PackageManager.PERMISSION_GRANTED) {
- requestPermissions(new String[] {permission.READ_EXTERNAL_STORAGE},
- MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);
- return;
- }
- initApp();
- }
-
- public void initApp() {
- int activeTab = MusicUtils.getIntPref(this, "activetab", R.id.artisttab);
- LogHelper.d(TAG, "initApp() activeTab = ", activeTab);
- if (activeTab != R.id.artisttab && activeTab != R.id.albumtab && activeTab != R.id.songtab
- && activeTab != R.id.playlisttab) {
- activeTab = R.id.artisttab;
- }
- MusicUtils.activateTab(this, activeTab);
- }
+ public void onCreate(Bundle icicle) {}
@Override
- public void onDestroy() {
- LogHelper.d(TAG, "onDestroy()");
- super.onDestroy();
- }
+ public void onDestroy() {}
@Override
public void onRequestPermissionsResult(
- int requestCode, String permissions[], int[] grantResults) {
- switch (requestCode) {
- case MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE: {
- if (grantResults.length == 0
- || grantResults[0] != PackageManager.PERMISSION_GRANTED) {
- finish();
- return;
- }
- initApp();
- }
- }
- }
+ int requestCode, String permissions[], int[] grantResults) {}
}
diff --git a/src/com/android/music/MusicPicker.java b/src/com/android/music/MusicPicker.java
deleted file mode 100644
index ea32ec9..0000000
--- a/src/com/android/music/MusicPicker.java
+++ /dev/null
@@ -1,688 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music;
-
-import android.app.ListActivity;
-import android.content.AsyncQueryHandler;
-import android.content.ContentUris;
-import android.content.Context;
-import android.content.Intent;
-import android.database.CharArrayBuffer;
-import android.database.Cursor;
-import android.media.AudioManager;
-import android.media.MediaPlayer;
-import android.media.RingtoneManager;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.provider.MediaStore;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.view.animation.AnimationUtils;
-import android.widget.ImageView;
-import android.widget.ListView;
-import android.widget.RadioButton;
-import android.widget.SectionIndexer;
-import android.widget.SimpleCursorAdapter;
-import android.widget.TextView;
-
-import java.io.IOException;
-import java.text.Collator;
-import java.util.Formatter;
-import java.util.Locale;
-
-/**
- * Activity allowing the user to select a music track on the device, and
- * return it to its caller. The music picker user interface is fairly
- * extensive, providing information about each track like the music
- * application (title, author, album, duration), as well as the ability to
- * previous tracks and sort them in different orders.
- *
- * <p>This class also illustrates how you can load data from a content
- * provider asynchronously, providing a good UI while doing so, perform
- * indexing of the content for use inside of a {@link FastScrollView}, and
- * perform filtering of the data as the user presses keys.
- */
-public class MusicPicker
- extends ListActivity implements View.OnClickListener, MediaPlayer.OnCompletionListener {
- static final boolean DBG = false;
- static final String TAG = "MusicPicker";
-
- /** Holds the previous state of the list, to restore after the async
- * query has completed. */
- static final String LIST_STATE_KEY = "liststate";
- /** Remember whether the list last had focus for restoring its state. */
- static final String FOCUS_KEY = "focused";
- /** Remember the last ordering mode for restoring state. */
- static final String SORT_MODE_KEY = "sortMode";
-
- /** Arbitrary number, doesn't matter since we only do one query type. */
- static final int MY_QUERY_TOKEN = 42;
-
- /** Menu item to sort the music list by track title. */
- static final int TRACK_MENU = Menu.FIRST;
- /** Menu item to sort the music list by album title. */
- static final int ALBUM_MENU = Menu.FIRST + 1;
- /** Menu item to sort the music list by artist name. */
- static final int ARTIST_MENU = Menu.FIRST + 2;
-
- /** These are the columns in the music cursor that we are interested in. */
- static final String[] CURSOR_COLS = new String[] {MediaStore.Audio.Media._ID,
- MediaStore.Audio.Media.TITLE, MediaStore.Audio.Media.TITLE_KEY,
- MediaStore.Audio.Media.DATA, MediaStore.Audio.Media.ALBUM,
- MediaStore.Audio.Media.ARTIST, MediaStore.Audio.Media.ARTIST_ID,
- MediaStore.Audio.Media.DURATION, MediaStore.Audio.Media.TRACK};
-
- /** Formatting optimization to avoid creating many temporary objects. */
- static StringBuilder sFormatBuilder = new StringBuilder();
- /** Formatting optimization to avoid creating many temporary objects. */
- static Formatter sFormatter = new Formatter(sFormatBuilder, Locale.getDefault());
- /** Formatting optimization to avoid creating many temporary objects. */
- static final Object[] sTimeArgs = new Object[5];
-
- /** Uri to the directory of all music being displayed. */
- Uri mBaseUri;
-
- /** This is the adapter used to display all of the tracks. */
- TrackListAdapter mAdapter;
- /** Our instance of QueryHandler used to perform async background queries. */
- QueryHandler mQueryHandler;
-
- /** Used to keep track of the last scroll state of the list. */
- Parcelable mListState = null;
- /** Used to keep track of whether the list last had focus. */
- boolean mListHasFocus;
-
- /** The current cursor on the music that is being displayed. */
- Cursor mCursor;
- /** The actual sort order the user has selected. */
- int mSortMode = -1;
- /** SQL order by string describing the currently selected sort order. */
- String mSortOrder;
-
- /** Container of the in-screen progress indicator, to be able to hide it
- * when done loading the initial cursor. */
- View mProgressContainer;
- /** Container of the list view hierarchy, to be able to show it when done
- * loading the initial cursor. */
- View mListContainer;
- /** Set to true when the list view has been shown for the first time. */
- boolean mListShown;
-
- /** View holding the okay button. */
- View mOkayButton;
- /** View holding the cancel button. */
- View mCancelButton;
-
- /** Which track row ID the user has last selected. */
- long mSelectedId = -1;
- /** Completel Uri that the user has last selected. */
- Uri mSelectedUri;
-
- /** If >= 0, we are currently playing a track for preview, and this is its
- * row ID. */
- long mPlayingId = -1;
-
- /** This is used for playing previews of the music files. */
- MediaPlayer mMediaPlayer;
-
- /**
- * A special implementation of SimpleCursorAdapter that knows how to bind
- * our cursor data to our list item structure, and takes care of other
- * advanced features such as indexing and filtering.
- */
- class TrackListAdapter extends SimpleCursorAdapter implements SectionIndexer {
- final ListView mListView;
-
- private final StringBuilder mBuilder = new StringBuilder();
- private final String mUnknownArtist;
- private final String mUnknownAlbum;
-
- private int mIdIdx;
- private int mTitleIdx;
- private int mArtistIdx;
- private int mAlbumIdx;
- private int mDurationIdx;
-
- private boolean mLoading = true;
- private int mIndexerSortMode;
- private MusicAlphabetIndexer mIndexer;
-
- class ViewHolder {
- TextView line1;
- TextView line2;
- TextView duration;
- RadioButton radio;
- ImageView play_indicator;
- CharArrayBuffer buffer1;
- char[] buffer2;
- }
-
- TrackListAdapter(Context context, ListView listView, int layout, String[] from, int[] to) {
- super(context, layout, null, from, to);
- mListView = listView;
- mUnknownArtist = context.getString(R.string.unknown_artist_name);
- mUnknownAlbum = context.getString(R.string.unknown_album_name);
- }
-
- /**
- * The mLoading flag is set while we are performing a background
- * query, to avoid displaying the "No music" empty view during
- * this time.
- */
- public void setLoading(boolean loading) {
- mLoading = loading;
- }
-
- @Override
- public boolean isEmpty() {
- if (mLoading) {
- // We don't want the empty state to show when loading.
- return false;
- } else {
- return super.isEmpty();
- }
- }
-
- @Override
- public View newView(Context context, Cursor cursor, ViewGroup parent) {
- View v = super.newView(context, cursor, parent);
- ViewHolder vh = new ViewHolder();
- vh.line1 = (TextView) v.findViewById(R.id.line1);
- vh.line2 = (TextView) v.findViewById(R.id.line2);
- vh.duration = (TextView) v.findViewById(R.id.duration);
- vh.radio = (RadioButton) v.findViewById(R.id.radio);
- vh.play_indicator = (ImageView) v.findViewById(R.id.play_indicator);
- vh.buffer1 = new CharArrayBuffer(100);
- vh.buffer2 = new char[200];
- v.setTag(vh);
- return v;
- }
-
- @Override
- public void bindView(View view, Context context, Cursor cursor) {
- ViewHolder vh = (ViewHolder) view.getTag();
-
- cursor.copyStringToBuffer(mTitleIdx, vh.buffer1);
- vh.line1.setText(vh.buffer1.data, 0, vh.buffer1.sizeCopied);
-
- int secs = cursor.getInt(mDurationIdx) / 1000;
- if (secs == 0) {
- vh.duration.setText("");
- } else {
- vh.duration.setText(MusicUtils.makeTimeString(context, secs));
- }
-
- final StringBuilder builder = mBuilder;
- builder.delete(0, builder.length());
-
- String name = cursor.getString(mAlbumIdx);
- if (name == null || name.equals("<unknown>")) {
- builder.append(mUnknownAlbum);
- } else {
- builder.append(name);
- }
- builder.append('\n');
- name = cursor.getString(mArtistIdx);
- if (name == null || name.equals("<unknown>")) {
- builder.append(mUnknownArtist);
- } else {
- builder.append(name);
- }
- int len = builder.length();
- if (vh.buffer2.length < len) {
- vh.buffer2 = new char[len];
- }
- builder.getChars(0, len, vh.buffer2, 0);
- vh.line2.setText(vh.buffer2, 0, len);
-
- // Update the checkbox of the item, based on which the user last
- // selected. Note that doing it this way means we must have the
- // list view update all of its items when the selected item
- // changes.
- final long id = cursor.getLong(mIdIdx);
- vh.radio.setChecked(id == mSelectedId);
- if (DBG)
- Log.v(TAG,
- "Binding id=" + id + " sel=" + mSelectedId + " playing=" + mPlayingId
- + " cursor=" + cursor);
-
- // Likewise, display the "now playing" icon if this item is
- // currently being previewed for the user.
- ImageView iv = vh.play_indicator;
- if (id == mPlayingId) {
- iv.setImageResource(R.drawable.indicator_ic_mp_playing_list);
- iv.setVisibility(View.VISIBLE);
- } else {
- iv.setVisibility(View.GONE);
- }
- }
-
- /**
- * This method is called whenever we receive a new cursor due to
- * an async query, and must take care of plugging the new one in
- * to the adapter.
- */
- @Override
- public void changeCursor(Cursor cursor) {
- super.changeCursor(cursor);
- if (DBG)
- Log.v(TAG, "Setting cursor to: " + cursor + " from: " + MusicPicker.this.mCursor);
-
- MusicPicker.this.mCursor = cursor;
-
- if (cursor != null) {
- // Retrieve indices of the various columns we are interested in.
- mIdIdx = cursor.getColumnIndex(MediaStore.Audio.Media._ID);
- mTitleIdx = cursor.getColumnIndex(MediaStore.Audio.Media.TITLE);
- mArtistIdx = cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST);
- mAlbumIdx = cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM);
- mDurationIdx = cursor.getColumnIndex(MediaStore.Audio.Media.DURATION);
-
- // If the sort mode has changed, or we haven't yet created an
- // indexer one, then create a new one that is indexing the
- // appropriate column based on the sort mode.
- if (mIndexerSortMode != mSortMode || mIndexer == null) {
- mIndexerSortMode = mSortMode;
- int idx = mTitleIdx;
- switch (mIndexerSortMode) {
- case ARTIST_MENU:
- idx = mArtistIdx;
- break;
- case ALBUM_MENU:
- idx = mAlbumIdx;
- break;
- }
- mIndexer = new MusicAlphabetIndexer(
- cursor, idx, getResources().getString(R.string.fast_scroll_alphabet));
-
- // If we have a valid indexer, but the cursor has changed since
- // its last use, then point it to the current cursor.
- } else {
- mIndexer.setCursor(cursor);
- }
- }
-
- // Ensure that the list is shown (and initial progress indicator
- // hidden) in case this is the first cursor we have gotten.
- makeListShown();
- }
-
- /**
- * This method is called from a background thread by the list view
- * when the user has typed a letter that should result in a filtering
- * of the displayed items. It returns a Cursor, when will then be
- * handed to changeCursor.
- */
- @Override
- public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
- if (DBG) Log.v(TAG, "Getting new cursor...");
- return doQuery(true, constraint.toString());
- }
-
- public int getPositionForSection(int section) {
- Cursor cursor = getCursor();
- if (cursor == null) {
- // No cursor, the section doesn't exist so just return 0
- return 0;
- }
-
- return mIndexer.getPositionForSection(section);
- }
-
- public int getSectionForPosition(int position) {
- return 0;
- }
-
- public Object[] getSections() {
- if (mIndexer != null) {
- return mIndexer.getSections();
- }
- return null;
- }
- }
-
- /**
- * This is our specialization of AsyncQueryHandler applies new cursors
- * to our state as they become available.
- */
- private final class QueryHandler extends AsyncQueryHandler {
- public QueryHandler(Context context) {
- super(context.getContentResolver());
- }
-
- @Override
- protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
- if (!isFinishing()) {
- // Update the adapter: we are no longer loading, and have
- // a new cursor for it.
- mAdapter.setLoading(false);
- mAdapter.changeCursor(cursor);
- setProgressBarIndeterminateVisibility(false);
-
- // Now that the cursor is populated again, it's possible to restore the list state
- if (mListState != null) {
- getListView().onRestoreInstanceState(mListState);
- if (mListHasFocus) {
- getListView().requestFocus();
- }
- mListHasFocus = false;
- mListState = null;
- }
- } else {
- cursor.close();
- }
- }
- }
-
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
-
- requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
-
- int sortMode = TRACK_MENU;
- if (icicle == null) {
- mSelectedUri =
- getIntent().getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI);
- } else {
- mSelectedUri = (Uri) icicle.getParcelable(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI);
- // Retrieve list state. This will be applied after the
- // QueryHandler has run
- mListState = icicle.getParcelable(LIST_STATE_KEY);
- mListHasFocus = icicle.getBoolean(FOCUS_KEY);
- sortMode = icicle.getInt(SORT_MODE_KEY, sortMode);
- }
- if (Intent.ACTION_GET_CONTENT.equals(getIntent().getAction())) {
- mBaseUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
- } else {
- mBaseUri = getIntent().getData();
- if (mBaseUri == null) {
- Log.w("MusicPicker", "No data URI given to PICK action");
- finish();
- return;
- }
- }
-
- setContentView(R.layout.music_picker);
-
- mSortOrder = MediaStore.Audio.Media.TITLE_KEY;
-
- final ListView listView = getListView();
-
- listView.setItemsCanFocus(false);
-
- mAdapter = new TrackListAdapter(
- this, listView, R.layout.music_picker_item, new String[] {}, new int[] {});
-
- setListAdapter(mAdapter);
-
- listView.setTextFilterEnabled(true);
-
- // We manually save/restore the listview state
- listView.setSaveEnabled(false);
-
- mQueryHandler = new QueryHandler(this);
-
- mProgressContainer = findViewById(R.id.progressContainer);
- mListContainer = findViewById(R.id.listContainer);
-
- mOkayButton = findViewById(R.id.okayButton);
- mOkayButton.setOnClickListener(this);
- mCancelButton = findViewById(R.id.cancelButton);
- mCancelButton.setOnClickListener(this);
-
- // If there is a currently selected Uri, then try to determine who
- // it is.
- if (mSelectedUri != null) {
- Uri.Builder builder = mSelectedUri.buildUpon();
- String path = mSelectedUri.getEncodedPath();
- int idx = path.lastIndexOf('/');
- if (idx >= 0) {
- path = path.substring(0, idx);
- }
- builder.encodedPath(path);
- Uri baseSelectedUri = builder.build();
- if (DBG) Log.v(TAG, "Selected Uri: " + mSelectedUri);
- if (DBG) Log.v(TAG, "Selected base Uri: " + baseSelectedUri);
- if (DBG) Log.v(TAG, "Base Uri: " + mBaseUri);
- if (baseSelectedUri.equals(mBaseUri)) {
- // If the base Uri of the selected Uri is the same as our
- // content's base Uri, then use the selection!
- mSelectedId = ContentUris.parseId(mSelectedUri);
- }
- }
-
- setSortMode(sortMode);
- }
-
- @Override
- public void onRestart() {
- super.onRestart();
- doQuery(false, null);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (setSortMode(item.getItemId())) {
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- menu.add(Menu.NONE, TRACK_MENU, Menu.NONE, R.string.sort_by_track);
- menu.add(Menu.NONE, ALBUM_MENU, Menu.NONE, R.string.sort_by_album);
- menu.add(Menu.NONE, ARTIST_MENU, Menu.NONE, R.string.sort_by_artist);
- return true;
- }
-
- @Override
- protected void onSaveInstanceState(Bundle icicle) {
- super.onSaveInstanceState(icicle);
- // Save list state in the bundle so we can restore it after the
- // QueryHandler has run
- icicle.putParcelable(LIST_STATE_KEY, getListView().onSaveInstanceState());
- icicle.putBoolean(FOCUS_KEY, getListView().hasFocus());
- icicle.putInt(SORT_MODE_KEY, mSortMode);
- }
-
- @Override
- public void onPause() {
- super.onPause();
- stopMediaPlayer();
- }
-
- @Override
- public void onStop() {
- super.onStop();
-
- // We don't want the list to display the empty state, since when we
- // resume it will still be there and show up while the new query is
- // happening. After the async query finishes in response to onResume()
- // setLoading(false) will be called.
- mAdapter.setLoading(true);
- mAdapter.changeCursor(null);
- }
-
- /**
- * Changes the current sort order, building the appropriate query string
- * for the selected order.
- */
- boolean setSortMode(int sortMode) {
- if (sortMode != mSortMode) {
- switch (sortMode) {
- case TRACK_MENU:
- mSortMode = sortMode;
- mSortOrder = MediaStore.Audio.Media.TITLE_KEY;
- doQuery(false, null);
- return true;
- case ALBUM_MENU:
- mSortMode = sortMode;
- mSortOrder = MediaStore.Audio.Media.ALBUM_KEY + " ASC, "
- + MediaStore.Audio.Media.TRACK + " ASC, "
- + MediaStore.Audio.Media.TITLE_KEY + " ASC";
- doQuery(false, null);
- return true;
- case ARTIST_MENU:
- mSortMode = sortMode;
- mSortOrder = MediaStore.Audio.Media.ARTIST_KEY + " ASC, "
- + MediaStore.Audio.Media.ALBUM_KEY + " ASC, "
- + MediaStore.Audio.Media.TRACK + " ASC, "
- + MediaStore.Audio.Media.TITLE_KEY + " ASC";
- doQuery(false, null);
- return true;
- }
- }
- return false;
- }
-
- /**
- * The first time this is called, we hide the large progress indicator
- * and show the list view, doing fade animations between them.
- */
- void makeListShown() {
- if (!mListShown) {
- mListShown = true;
- mProgressContainer.startAnimation(
- AnimationUtils.loadAnimation(this, android.R.anim.fade_out));
- mProgressContainer.setVisibility(View.GONE);
- mListContainer.startAnimation(
- AnimationUtils.loadAnimation(this, android.R.anim.fade_in));
- mListContainer.setVisibility(View.VISIBLE);
- }
- }
-
- /**
- * Common method for performing a query of the music database, called for
- * both top-level queries and filtering.
- *
- * @param sync If true, this query should be done synchronously and the
- * resulting cursor returned. If false, it will be done asynchronously and
- * null returned.
- * @param filterstring If non-null, this is a filter to apply to the query.
- */
- Cursor doQuery(boolean sync, String filterstring) {
- // Cancel any pending queries
- mQueryHandler.cancelOperation(MY_QUERY_TOKEN);
-
- StringBuilder where = new StringBuilder();
- where.append(MediaStore.Audio.Media.TITLE + " != ''");
-
- // We want to show all audio files, even recordings. Enforcing the
- // following condition would hide recordings.
- // where.append(" AND " + MediaStore.Audio.Media.IS_MUSIC + "=1");
-
- Uri uri = mBaseUri;
- if (!TextUtils.isEmpty(filterstring)) {
- uri = uri.buildUpon().appendQueryParameter("filter", Uri.encode(filterstring)).build();
- }
-
- if (sync) {
- try {
- return getContentResolver().query(
- uri, CURSOR_COLS, where.toString(), null, mSortOrder);
- } catch (UnsupportedOperationException ex) {
- }
- } else {
- mAdapter.setLoading(true);
- setProgressBarIndeterminateVisibility(true);
- mQueryHandler.startQuery(
- MY_QUERY_TOKEN, null, uri, CURSOR_COLS, where.toString(), null, mSortOrder);
- }
- return null;
- }
-
- @Override
- protected void onListItemClick(ListView l, View v, int position, long id) {
- mCursor.moveToPosition(position);
- if (DBG)
- Log.v(TAG,
- "Click on " + position + " (id=" + id + ", cursid="
- + mCursor.getLong(mCursor.getColumnIndex(MediaStore.Audio.Media._ID))
- + ") in cursor " + mCursor + " adapter=" + l.getAdapter());
- setSelected(mCursor);
- }
-
- void setSelected(Cursor c) {
- Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
- long newId = mCursor.getLong(mCursor.getColumnIndex(MediaStore.Audio.Media._ID));
- mSelectedUri = ContentUris.withAppendedId(uri, newId);
-
- mSelectedId = newId;
- if (newId != mPlayingId || mMediaPlayer == null) {
- stopMediaPlayer();
- mMediaPlayer = new MediaPlayer();
- try {
- mMediaPlayer.setDataSource(this, mSelectedUri);
- mMediaPlayer.setOnCompletionListener(this);
- mMediaPlayer.setAudioStreamType(AudioManager.STREAM_RING);
- mMediaPlayer.prepare();
- mMediaPlayer.start();
- mPlayingId = newId;
- getListView().invalidateViews();
- } catch (IOException e) {
- Log.w("MusicPicker", "Unable to play track", e);
- }
- } else if (mMediaPlayer != null) {
- stopMediaPlayer();
- getListView().invalidateViews();
- }
- }
-
- public void onCompletion(MediaPlayer mp) {
- if (mMediaPlayer == mp) {
- mp.stop();
- mp.release();
- mMediaPlayer = null;
- mPlayingId = -1;
- getListView().invalidateViews();
- }
- }
-
- void stopMediaPlayer() {
- if (mMediaPlayer != null) {
- mMediaPlayer.stop();
- mMediaPlayer.release();
- mMediaPlayer = null;
- mPlayingId = -1;
- }
- }
-
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.okayButton:
- if (mSelectedId >= 0) {
- setResult(RESULT_OK, new Intent().setData(mSelectedUri));
- finish();
- }
- break;
-
- case R.id.cancelButton:
- finish();
- break;
- }
- }
-}
\ No newline at end of file
diff --git a/src/com/android/music/MusicUtils.java b/src/com/android/music/MusicUtils.java
deleted file mode 100644
index a8a93e1..0000000
--- a/src/com/android/music/MusicUtils.java
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music;
-
-import android.app.Activity;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.PixelFormat;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.media.MediaMetadata;
-import android.media.session.MediaController;
-import android.net.Uri;
-import android.provider.MediaStore;
-import android.view.View;
-import android.widget.TabWidget;
-import android.widget.TextView;
-import com.android.music.utils.LogHelper;
-import com.android.music.utils.MusicProvider;
-
-import java.util.Formatter;
-import java.util.Iterator;
-import java.util.Locale;
-
-/*
-Static methods useful for activities
- */
-public class MusicUtils {
- private static final String TAG = LogHelper.makeLogTag(MusicUtils.class);
-
- public static final String TAG_MEDIA_ID = "__MEDIA_ID";
- public static final String TAG_PARENT_ITEM = "__PARENT_ITEM";
- public static final String TAG_WITH_TABS = "__WITH_TABS";
-
- // A really simple BitmapDrawable-like class, that doesn't do
- // scaling, dithering or filtering.
- private static class FastBitmapDrawable extends Drawable {
- private Bitmap mBitmap;
- public FastBitmapDrawable(Bitmap b) {
- mBitmap = b;
- }
- @Override
- public void draw(Canvas canvas) {
- canvas.drawBitmap(mBitmap, 0, 0, null);
- }
- @Override
- public int getOpacity() {
- return PixelFormat.OPAQUE;
- }
- @Override
- public void setAlpha(int alpha) {}
- @Override
- public void setColorFilter(ColorFilter cf) {}
- }
-
- public static Bitmap resizeBitmap(Bitmap bitmap, Bitmap ref) {
- int w = ref.getWidth();
- int h = ref.getHeight();
- return Bitmap.createScaledBitmap(bitmap, w, h, false);
- }
-
- public static Drawable getDrawableBitmap(Bitmap bitmap, BitmapDrawable defaultArtwork) {
- final Bitmap icon = defaultArtwork.getBitmap();
- int w = icon.getWidth();
- int h = icon.getHeight();
- bitmap = Bitmap.createScaledBitmap(bitmap, w, h, false);
- return new FastBitmapDrawable(bitmap);
- }
-
- public static String makeAlbumsLabel(
- Context context, int numalbums, int numsongs, boolean isUnknown) {
- // There are two formats for the albums/songs information:
- // "N Song(s)" - used for unknown artist/album
- // "N Album(s)" - used for known albums
-
- StringBuilder songs_albums = new StringBuilder();
-
- Resources r = context.getResources();
- if (isUnknown) {
- if (numsongs == 1) {
- songs_albums.append(context.getString(R.string.onesong));
- } else {
- String f = r.getQuantityText(R.plurals.Nsongs, numsongs).toString();
- sFormatBuilder.setLength(0);
- sFormatter.format(f, Integer.valueOf(numsongs));
- songs_albums.append(sFormatBuilder);
- }
- } else {
- String f = r.getQuantityText(R.plurals.Nalbums, numalbums).toString();
- sFormatBuilder.setLength(0);
- sFormatter.format(f, Integer.valueOf(numalbums));
- songs_albums.append(sFormatBuilder);
- songs_albums.append(context.getString(R.string.albumsongseparator));
- }
- return songs_albums.toString();
- }
-
- /**
- * This is now only used for the query screen
- */
- public static String makeAlbumsSongsLabel(
- Context context, int numalbums, int numsongs, boolean isUnknown) {
- // There are several formats for the albums/songs information:
- // "1 Song" - used if there is only 1 song
- // "N Songs" - used for the "unknown artist" item
- // "1 Album"/"N Songs"
- // "N Album"/"M Songs"
- // Depending on locale, these may need to be further subdivided
-
- StringBuilder songs_albums = new StringBuilder();
-
- if (numsongs == 1) {
- songs_albums.append(context.getString(R.string.onesong));
- } else {
- Resources r = context.getResources();
- if (!isUnknown) {
- String f = r.getQuantityText(R.plurals.Nalbums, numalbums).toString();
- sFormatBuilder.setLength(0);
- sFormatter.format(f, Integer.valueOf(numalbums));
- songs_albums.append(sFormatBuilder);
- songs_albums.append(context.getString(R.string.albumsongseparator));
- }
- String f = r.getQuantityText(R.plurals.Nsongs, numsongs).toString();
- sFormatBuilder.setLength(0);
- sFormatter.format(f, Integer.valueOf(numsongs));
- songs_albums.append(sFormatBuilder);
- }
- return songs_albums.toString();
- }
-
- /* Try to use String.format() as little as possible, because it creates a
- * new Formatter every time you call it, which is very inefficient.
- * Reusing an existing Formatter more than tripled the speed of
- * makeTimeString().
- * This Formatter/StringBuilder are also used by makeAlbumSongsLabel()
- */
- private static StringBuilder sFormatBuilder = new StringBuilder();
- private static Formatter sFormatter = new Formatter(sFormatBuilder, Locale.getDefault());
- private static final Object[] sTimeArgs = new Object[5];
-
- public static String makeTimeString(Context context, long secs) {
- String durationformat = context.getString(
- secs < 3600 ? R.string.durationformatshort : R.string.durationformatlong);
-
- /* Provide multiple arguments so the format can be changed easily
- * by modifying the xml.
- */
- sFormatBuilder.setLength(0);
-
- final Object[] timeArgs = sTimeArgs;
- timeArgs[0] = secs / 3600;
- timeArgs[1] = secs / 60;
- timeArgs[2] = (secs / 60) % 60;
- timeArgs[3] = secs;
- timeArgs[4] = secs % 60;
-
- return sFormatter.format(durationformat, timeArgs).toString();
- }
-
- static int getIntPref(Context context, String name, int def) {
- SharedPreferences prefs =
- context.getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE);
- return prefs.getInt(name, def);
- }
-
- static void setIntPref(Context context, String name, int value) {
- SharedPreferences prefs =
- context.getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE);
- Editor ed = prefs.edit();
- ed.putInt(name, value);
- SharedPreferencesCompat.apply(ed);
- }
-
- static int sActiveTabIndex = -1;
-
- static boolean updateButtonBar(Activity a, int highlight) {
- final TabWidget ll = (TabWidget) a.findViewById(R.id.buttonbar);
- boolean withtabs = false;
- Intent intent = a.getIntent();
- if (intent != null) {
- withtabs = intent.getBooleanExtra(MusicUtils.TAG_WITH_TABS, false);
- }
-
- if (highlight == 0 || !withtabs) {
- ll.setVisibility(View.GONE);
- return withtabs;
- } else if (withtabs) {
- ll.setVisibility(View.VISIBLE);
- }
- for (int i = ll.getChildCount() - 1; i >= 0; i--) {
- View v = ll.getChildAt(i);
- boolean isActive = (v.getId() == highlight);
- if (isActive) {
- ll.setCurrentTab(i);
- sActiveTabIndex = i;
- }
- v.setTag(i);
- v.setOnFocusChangeListener(new View.OnFocusChangeListener() {
-
- public void onFocusChange(View v, boolean hasFocus) {
- if (hasFocus) {
- for (int i = 0; i < ll.getTabCount(); i++) {
- if (ll.getChildTabViewAt(i) == v) {
- ll.setCurrentTab(i);
- processTabClick((Activity) ll.getContext(), v,
- ll.getChildAt(sActiveTabIndex).getId());
- break;
- }
- }
- }
- }
- });
-
- v.setOnClickListener(new View.OnClickListener() {
-
- public void onClick(View v) {
- processTabClick(
- (Activity) ll.getContext(), v, ll.getChildAt(sActiveTabIndex).getId());
- }
- });
- }
- return withtabs;
- }
-
- static void processTabClick(Activity a, View v, int current) {
- int id = v.getId();
- if (id == current) {
- return;
- }
-
- final TabWidget ll = (TabWidget) a.findViewById(R.id.buttonbar);
-
- activateTab(a, id);
- if (id != R.id.nowplayingtab) {
- ll.setCurrentTab((Integer) v.getTag());
- setIntPref(a, "activetab", id);
- }
- }
-
- static void activateTab(Activity a, int id) {
- Intent intent = new Intent(Intent.ACTION_PICK);
- switch (id) {
- case R.id.artisttab:
- intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/artistalbum");
- break;
- case R.id.albumtab:
- intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/album");
- break;
- case R.id.songtab:
- intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track");
- break;
- case R.id.playlisttab:
- intent.setDataAndType(Uri.EMPTY, MediaStore.Audio.Playlists.CONTENT_TYPE);
- break;
- case R.id.nowplayingtab:
- intent = new Intent(a, MediaPlaybackActivity.class);
- a.startActivity(intent);
- // fall through and return
- default:
- return;
- }
- intent.putExtra(MusicUtils.TAG_WITH_TABS, true);
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- a.startActivity(intent);
- a.finish();
- a.overridePendingTransition(0, 0);
- }
-
- static void updateNowPlaying(Activity a) {
- View nowPlayingView = a.findViewById(R.id.nowplaying);
- if (nowPlayingView == null) {
- return;
- }
- MediaController controller = a.getMediaController();
- if (controller != null) {
- MediaMetadata metadata = controller.getMetadata();
- if (metadata != null) {
- TextView title = (TextView) nowPlayingView.findViewById(R.id.title);
- TextView artist = (TextView) nowPlayingView.findViewById(R.id.artist);
- title.setText(metadata.getString(MediaMetadata.METADATA_KEY_TITLE));
- String artistName = metadata.getString(MediaMetadata.METADATA_KEY_ARTIST);
- if (MusicProvider.UNKOWN.equals(artistName)) {
- artistName = a.getString(R.string.unknown_artist_name);
- }
- artist.setText(artistName);
- nowPlayingView.setVisibility(View.VISIBLE);
- nowPlayingView.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- Context c = v.getContext();
- c.startActivity(new Intent(c, MediaPlaybackActivity.class));
- }
- });
- return;
- }
- }
- nowPlayingView.setVisibility(View.GONE);
- }
-}
diff --git a/src/com/android/music/PlaylistBrowserActivity.java b/src/com/android/music/PlaylistBrowserActivity.java
deleted file mode 100644
index fccee6d..0000000
--- a/src/com/android/music/PlaylistBrowserActivity.java
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music;
-
-import android.app.Activity;
-import android.app.ListActivity;
-import android.content.*;
-import android.database.Cursor;
-import android.database.MatrixCursor;
-import android.database.MergeCursor;
-import android.database.sqlite.SQLiteException;
-import android.media.AudioManager;
-import android.media.MediaDescription;
-import android.media.MediaMetadata;
-import android.media.browse.MediaBrowser;
-import android.media.session.MediaController;
-import android.media.session.MediaSession;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.MediaStore;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.widget.*;
-import com.android.music.utils.LogHelper;
-import com.android.music.utils.MediaIDHelper;
-
-import java.text.Collator;
-import java.util.ArrayList;
-import java.util.List;
-
-public class PlaylistBrowserActivity
- extends ListActivity implements View.OnCreateContextMenuListener {
- private static final String TAG = LogHelper.makeLogTag(PlaylistBrowserActivity.class);
- private PlaylistListAdapter mAdapter;
- boolean mAdapterSent;
- private static final MediaBrowser.MediaItem DEFAULT_PARENT_ITEM = new MediaBrowser.MediaItem(
- new MediaDescription.Builder()
- .setMediaId(MediaIDHelper.MEDIA_ID_MUSICS_BY_PLAYLIST)
- .setTitle("Playlists")
- .build(),
- MediaBrowser.MediaItem.FLAG_BROWSABLE);
-
- private MediaBrowser mMediaBrowser;
- private MediaBrowser.MediaItem mParentItem;
-
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- LogHelper.d(TAG, "onCreate()");
- // Process past states
- Intent intent = getIntent();
- if (icicle != null) {
- LogHelper.d(TAG, "Launch by saved instance state");
- mParentItem = icicle.getParcelable(MusicUtils.TAG_PARENT_ITEM);
- MusicUtils.updateNowPlaying(this);
- } else if (intent != null) {
- LogHelper.d(TAG, "Launch by intent");
- mParentItem = intent.getExtras().getParcelable(MusicUtils.TAG_PARENT_ITEM);
- }
- if (mParentItem == null) {
- LogHelper.d(TAG, "Launch by default parameters");
- mParentItem = DEFAULT_PARENT_ITEM;
- }
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setVolumeControlStream(AudioManager.STREAM_MUSIC);
-
- setTitle(R.string.playlists_title);
- setContentView(R.layout.media_picker_activity);
- MusicUtils.updateButtonBar(this, R.id.playlisttab);
- ListView lv = getListView();
- lv.setOnCreateContextMenuListener(this);
- lv.setTextFilterEnabled(true);
-
- mAdapter = (PlaylistListAdapter) getLastNonConfigurationInstance();
- if (mAdapter == null) {
- // Log.i("@@@", "starting query");
- mAdapter = new PlaylistListAdapter(this, R.layout.track_list_item);
- setTitle(R.string.working_playlists);
- } else {
- mAdapter.setActivity(this);
- }
- setListAdapter(mAdapter);
- Log.d(TAG, "Creating MediaBrowser");
- mMediaBrowser = new MediaBrowser(this, new ComponentName(this, MediaPlaybackService.class),
- mConnectionCallback, null);
- }
-
- @Override
- public Object onRetainNonConfigurationInstance() {
- PlaylistListAdapter a = mAdapter;
- mAdapterSent = true;
- return a;
- }
-
- @Override
- public void onDestroy() {
- setListAdapter(null);
- mAdapter = null;
- super.onDestroy();
- }
-
- @Override
- public void onResume() {
- super.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- }
-
- @Override
- public void onStart() {
- Log.d(TAG, "onStart()");
- super.onStart();
- mMediaBrowser.connect();
- }
-
- @Override
- public void onStop() {
- Log.d(TAG, "onStop()");
- super.onStop();
- mMediaBrowser.disconnect();
- }
-
- private MediaBrowser.SubscriptionCallback mSubscriptionCallback =
- new MediaBrowser.SubscriptionCallback() {
-
- @Override
- public void onChildrenLoaded(
- String parentId, List<MediaBrowser.MediaItem> children) {
- mAdapter.clear();
- mAdapter.notifyDataSetInvalidated();
- for (MediaBrowser.MediaItem item : children) {
- mAdapter.add(item);
- }
- mAdapter.notifyDataSetChanged();
- }
-
- @Override
- public void onError(String id) {
- Toast.makeText(getApplicationContext(), R.string.error_loading_media,
- Toast.LENGTH_LONG)
- .show();
- }
- };
-
- private MediaBrowser.ConnectionCallback mConnectionCallback =
- new MediaBrowser.ConnectionCallback() {
- @Override
- public void onConnected() {
- Log.d(TAG, "onConnected: session token " + mMediaBrowser.getSessionToken());
- mMediaBrowser.subscribe(mParentItem.getMediaId(), mSubscriptionCallback);
- if (mMediaBrowser.getSessionToken() == null) {
- throw new IllegalArgumentException("No Session token");
- }
- MediaController mediaController = new MediaController(
- PlaylistBrowserActivity.this, mMediaBrowser.getSessionToken());
- mediaController.registerCallback(mMediaControllerCallback);
- PlaylistBrowserActivity.this.setMediaController(mediaController);
- if (mediaController.getMetadata() != null) {
- MusicUtils.updateNowPlaying(PlaylistBrowserActivity.this);
- }
- }
-
- @Override
- public void onConnectionFailed() {
- Log.d(TAG, "onConnectionFailed");
- }
-
- @Override
- public void onConnectionSuspended() {
- Log.d(TAG, "onConnectionSuspended");
- PlaylistBrowserActivity.this.setMediaController(null);
- }
- };
-
- private MediaController.Callback mMediaControllerCallback = new MediaController.Callback() {
- @Override
- public void onMetadataChanged(MediaMetadata metadata) {
- super.onMetadataChanged(metadata);
- MusicUtils.updateNowPlaying(PlaylistBrowserActivity.this);
- }
- };
-
- private class PlaylistListAdapter extends ArrayAdapter<MediaBrowser.MediaItem> {
- private int mLayoutId;
- private Activity mActivity;
-
- PlaylistListAdapter(PlaylistBrowserActivity currentactivity, int layout) {
- super(currentactivity, layout);
- mActivity = currentactivity;
- mLayoutId = layout;
- }
-
- private class ViewHolder {
- TextView line1;
- TextView line2;
- ImageView icon;
- ImageView play_indicator;
- }
-
- public void setActivity(PlaylistBrowserActivity newactivity) {
- mActivity = newactivity;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = LayoutInflater.from(getContext()).inflate(mLayoutId, parent, false);
- ViewHolder vhx = new ViewHolder();
- vhx.line1 = (TextView) convertView.findViewById(R.id.line1);
- vhx.line2 = (TextView) convertView.findViewById(R.id.line2);
- vhx.icon = (ImageView) convertView.findViewById(R.id.icon);
- vhx.play_indicator = (ImageView) convertView.findViewById(R.id.play_indicator);
- convertView.setTag(vhx);
- }
- ViewHolder vh = (ViewHolder) convertView.getTag();
- MediaBrowser.MediaItem item = getItem(position);
- vh.line1.setText(item.getDescription().getTitle());
- vh.line2.setVisibility(View.GONE);
- vh.play_indicator.setVisibility(View.GONE);
- vh.icon.setImageResource(R.drawable.ic_mp_playlist_list);
- ViewGroup.LayoutParams p = vh.icon.getLayoutParams();
- p.width = ViewGroup.LayoutParams.WRAP_CONTENT;
- p.height = ViewGroup.LayoutParams.WRAP_CONTENT;
- return convertView;
- }
- }
-
- @Override
- protected void onListItemClick(ListView l, View v, int position, long id) {
- MediaBrowser.MediaItem item = mAdapter.getItem(position);
- Intent intent = new Intent(Intent.ACTION_PICK);
- intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track");
- intent.putExtra(MusicUtils.TAG_PARENT_ITEM, item);
- startActivity(intent);
- }
-}
diff --git a/src/com/android/music/RepeatingImageButton.java b/src/com/android/music/RepeatingImageButton.java
deleted file mode 100644
index 7dc5a65..0000000
--- a/src/com/android/music/RepeatingImageButton.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music;
-
-import android.content.Context;
-import android.os.SystemClock;
-import android.util.AttributeSet;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.View;
-import android.widget.ImageButton;
-
-/**
- * A button that will repeatedly call a 'listener' method
- * as long as the button is pressed.
- */
-public class RepeatingImageButton extends ImageButton {
- private long mStartTime;
- private int mRepeatCount;
- private RepeatListener mListener;
- private long mInterval = 500;
-
- public RepeatingImageButton(Context context) {
- this(context, null);
- }
-
- public RepeatingImageButton(Context context, AttributeSet attrs) {
- this(context, attrs, android.R.attr.imageButtonStyle);
- }
-
- public RepeatingImageButton(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- setFocusable(true);
- setLongClickable(true);
- }
-
- /**
- * Sets the listener to be called while the button is pressed and
- * the interval in milliseconds with which it will be called.
- * @param l The listener that will be called
- * @param interval The interval in milliseconds for calls
- */
- public void setRepeatListener(RepeatListener l, long interval) {
- mListener = l;
- mInterval = interval;
- }
-
- @Override
- public boolean performLongClick() {
- mStartTime = SystemClock.elapsedRealtime();
- mRepeatCount = 0;
- post(mRepeater);
- return true;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_UP) {
- // remove the repeater, but call the hook one more time
- removeCallbacks(mRepeater);
- if (mStartTime != 0) {
- doRepeat(true);
- mStartTime = 0;
- }
- }
- return super.onTouchEvent(event);
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_CENTER:
- case KeyEvent.KEYCODE_ENTER:
- // need to call super to make long press work, but return
- // true so that the application doesn't get the down event.
- super.onKeyDown(keyCode, event);
- return true;
- }
- return super.onKeyDown(keyCode, event);
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_CENTER:
- case KeyEvent.KEYCODE_ENTER:
- // remove the repeater, but call the hook one more time
- removeCallbacks(mRepeater);
- if (mStartTime != 0) {
- doRepeat(true);
- mStartTime = 0;
- }
- }
- return super.onKeyUp(keyCode, event);
- }
-
- private Runnable mRepeater = new Runnable() {
- public void run() {
- doRepeat(false);
- if (isPressed()) {
- postDelayed(this, mInterval);
- }
- }
- };
-
- private void doRepeat(boolean last) {
- long now = SystemClock.elapsedRealtime();
- if (mListener != null) {
- mListener.onRepeat(this, now - mStartTime, last ? -1 : mRepeatCount++);
- }
- }
-
- public interface RepeatListener {
- /**
- * This method will be called repeatedly at roughly the interval
- * specified in setRepeatListener(), for as long as the button
- * is pressed.
- * @param v The button as a View.
- * @param duration The number of milliseconds the button has been pressed so far.
- * @param repeatcount The number of previous calls in this sequence.
- * If this is going to be the last call in this sequence (i.e. the user
- * just stopped pressing the button), the value will be -1.
- */
- void onRepeat(View v, long duration, int repeatcount);
- }
-}
diff --git a/src/com/android/music/SharedPreferencesCompat.java b/src/com/android/music/SharedPreferencesCompat.java
deleted file mode 100644
index 92780a6..0000000
--- a/src/com/android/music/SharedPreferencesCompat.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music;
-
-import android.content.SharedPreferences;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-/**
- * Reflection utils to call SharedPreferences$Editor.apply when possible,
- * falling back to commit when apply isn't available.
- */
-public class SharedPreferencesCompat {
- private static final Method sApplyMethod = findApplyMethod();
-
- private static Method findApplyMethod() {
- try {
- Class cls = SharedPreferences.Editor.class;
- return cls.getMethod("apply");
- } catch (NoSuchMethodException unused) {
- // fall through
- }
- return null;
- }
-
- public static void apply(SharedPreferences.Editor editor) {
- if (sApplyMethod != null) {
- try {
- sApplyMethod.invoke(editor);
- return;
- } catch (InvocationTargetException unused) {
- // fall through
- } catch (IllegalAccessException unused) {
- // fall through
- }
- }
- editor.commit();
- }
-}
diff --git a/src/com/android/music/TouchInterceptor.java b/src/com/android/music/TouchInterceptor.java
deleted file mode 100644
index eee7c87..0000000
--- a/src/com/android/music/TouchInterceptor.java
+++ /dev/null
@@ -1,467 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LevelListDrawable;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.GestureDetector;
-import android.view.Gravity;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.view.GestureDetector.SimpleOnGestureListener;
-import android.widget.AdapterView;
-import android.widget.ImageView;
-import android.widget.ListView;
-
-public class TouchInterceptor extends ListView {
- private ImageView mDragView;
- private WindowManager mWindowManager;
- private WindowManager.LayoutParams mWindowParams;
- /**
- * At which position is the item currently being dragged. Note that this
- * takes in to account header items.
- */
- private int mDragPos;
- /**
- * At which position was the item being dragged originally
- */
- private int mSrcDragPos;
- private int mDragPointX; // at what x offset inside the item did the user grab it
- private int mDragPointY; // at what y offset inside the item did the user grab it
- private int mXOffset; // the difference between screen coordinates and coordinates in this view
- private int mYOffset; // the difference between screen coordinates and coordinates in this view
- private DragListener mDragListener;
- private DropListener mDropListener;
- private RemoveListener mRemoveListener;
- private int mUpperBound;
- private int mLowerBound;
- private int mHeight;
- private GestureDetector mGestureDetector;
- private static final int FLING = 0;
- private static final int SLIDE = 1;
- private static final int TRASH = 2;
- private int mRemoveMode = -1;
- private Rect mTempRect = new Rect();
- private Bitmap mDragBitmap;
- private final int mTouchSlop;
- private int mItemHeightNormal;
- private int mItemHeightExpanded;
- private int mItemHeightHalf;
- private Drawable mTrashcan;
-
- public TouchInterceptor(Context context, AttributeSet attrs) {
- super(context, attrs);
- SharedPreferences pref = context.getSharedPreferences("Music", 0);
- mRemoveMode = pref.getInt("deletemode", -1);
- mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
- Resources res = getResources();
- mItemHeightNormal = res.getDimensionPixelSize(R.dimen.normal_height);
- mItemHeightHalf = mItemHeightNormal / 2;
- mItemHeightExpanded = res.getDimensionPixelSize(R.dimen.expanded_height);
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (mRemoveListener != null && mGestureDetector == null) {
- if (mRemoveMode == FLING) {
- mGestureDetector = new GestureDetector(getContext(), new SimpleOnGestureListener() {
- @Override
- public boolean onFling(
- MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
- if (mDragView != null) {
- if (velocityX > 1000) {
- Rect r = mTempRect;
- mDragView.getDrawingRect(r);
- if (e2.getX() > r.right * 2 / 3) {
- // fast fling right with release near the right edge of the
- // screen
- stopDragging();
- mRemoveListener.remove(mSrcDragPos);
- unExpandViews(true);
- }
- }
- // flinging while dragging should have no effect
- return true;
- }
- return false;
- }
- });
- }
- }
- if (mDragListener != null || mDropListener != null) {
- switch (ev.getAction()) {
- case MotionEvent.ACTION_DOWN:
- int x = (int) ev.getX();
- int y = (int) ev.getY();
- int itemnum = pointToPosition(x, y);
- if (itemnum == AdapterView.INVALID_POSITION) {
- break;
- }
- ViewGroup item = (ViewGroup) getChildAt(itemnum - getFirstVisiblePosition());
- mDragPointX = x - item.getLeft();
- mDragPointY = y - item.getTop();
- mXOffset = ((int) ev.getRawX()) - x;
- mYOffset = ((int) ev.getRawY()) - y;
- // The left side of the item is the grabber for dragging the item
- if (x < 64) {
- item.setDrawingCacheEnabled(true);
- // Create a copy of the drawing cache so that it does not get recycled
- // by the framework when the list tries to clean up memory
- Bitmap bitmap = Bitmap.createBitmap(item.getDrawingCache());
- startDragging(bitmap, x, y);
- mDragPos = itemnum;
- mSrcDragPos = mDragPos;
- mHeight = getHeight();
- int touchSlop = mTouchSlop;
- mUpperBound = Math.min(y - touchSlop, mHeight / 3);
- mLowerBound = Math.max(y + touchSlop, mHeight * 2 / 3);
- return false;
- }
- stopDragging();
- break;
- }
- }
- return super.onInterceptTouchEvent(ev);
- }
-
- /*
- * pointToPosition() doesn't consider invisible views, but we
- * need to, so implement a slightly different version.
- */
- private int myPointToPosition(int x, int y) {
- if (y < 0) {
- // when dragging off the top of the screen, calculate position
- // by going back from a visible item
- int pos = myPointToPosition(x, y + mItemHeightNormal);
- if (pos > 0) {
- return pos - 1;
- }
- }
-
- Rect frame = mTempRect;
- final int count = getChildCount();
- for (int i = count - 1; i >= 0; i--) {
- final View child = getChildAt(i);
- child.getHitRect(frame);
- if (frame.contains(x, y)) {
- return getFirstVisiblePosition() + i;
- }
- }
- return INVALID_POSITION;
- }
-
- private int getItemForPosition(int y) {
- int adjustedy = y - mDragPointY - mItemHeightHalf;
- int pos = myPointToPosition(0, adjustedy);
- if (pos >= 0) {
- if (pos <= mSrcDragPos) {
- pos += 1;
- }
- } else if (adjustedy < 0) {
- // this shouldn't happen anymore now that myPointToPosition deals
- // with this situation
- pos = 0;
- }
- return pos;
- }
-
- private void adjustScrollBounds(int y) {
- if (y >= mHeight / 3) {
- mUpperBound = mHeight / 3;
- }
- if (y <= mHeight * 2 / 3) {
- mLowerBound = mHeight * 2 / 3;
- }
- }
-
- /*
- * Restore size and visibility for all listitems
- */
- private void unExpandViews(boolean deletion) {
- for (int i = 0;; i++) {
- View v = getChildAt(i);
- if (v == null) {
- if (deletion) {
- // HACK force update of mItemCount
- int position = getFirstVisiblePosition();
- int y = getChildAt(0).getTop();
- setAdapter(getAdapter());
- setSelectionFromTop(position, y);
- // end hack
- }
- try {
- layoutChildren(); // force children to be recreated where needed
- v = getChildAt(i);
- } catch (IllegalStateException ex) {
- // layoutChildren throws this sometimes, presumably because we're
- // in the process of being torn down but are still getting touch
- // events
- }
- if (v == null) {
- return;
- }
- }
- ViewGroup.LayoutParams params = v.getLayoutParams();
- params.height = mItemHeightNormal;
- v.setLayoutParams(params);
- v.setVisibility(View.VISIBLE);
- }
- }
-
- /* Adjust visibility and size to make it appear as though
- * an item is being dragged around and other items are making
- * room for it:
- * If dropping the item would result in it still being in the
- * same place, then make the dragged listitem's size normal,
- * but make the item invisible.
- * Otherwise, if the dragged listitem is still on screen, make
- * it as small as possible and expand the item below the insert
- * point.
- * If the dragged item is not on screen, only expand the item
- * below the current insertpoint.
- */
- private void doExpansion() {
- int childnum = mDragPos - getFirstVisiblePosition();
- if (mDragPos > mSrcDragPos) {
- childnum++;
- }
- int numheaders = getHeaderViewsCount();
-
- View first = getChildAt(mSrcDragPos - getFirstVisiblePosition());
- for (int i = 0;; i++) {
- View vv = getChildAt(i);
- if (vv == null) {
- break;
- }
-
- int height = mItemHeightNormal;
- int visibility = View.VISIBLE;
- if (mDragPos < numheaders && i == numheaders) {
- // dragging on top of the header item, so adjust the item below
- // instead
- if (vv.equals(first)) {
- visibility = View.INVISIBLE;
- } else {
- height = mItemHeightExpanded;
- }
- } else if (vv.equals(first)) {
- // processing the item that is being dragged
- if (mDragPos == mSrcDragPos || getPositionForView(vv) == getCount() - 1) {
- // hovering over the original location
- visibility = View.INVISIBLE;
- } else {
- // not hovering over it
- // Ideally the item would be completely gone, but neither
- // setting its size to 0 nor settings visibility to GONE
- // has the desired effect.
- height = 1;
- }
- } else if (i == childnum) {
- if (mDragPos >= numheaders && mDragPos < getCount() - 1) {
- height = mItemHeightExpanded;
- }
- }
- ViewGroup.LayoutParams params = vv.getLayoutParams();
- params.height = height;
- vv.setLayoutParams(params);
- vv.setVisibility(visibility);
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- if (mGestureDetector != null) {
- mGestureDetector.onTouchEvent(ev);
- }
- if ((mDragListener != null || mDropListener != null) && mDragView != null) {
- int action = ev.getAction();
- switch (action) {
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL:
- Rect r = mTempRect;
- mDragView.getDrawingRect(r);
- stopDragging();
- if (mRemoveMode == SLIDE && ev.getX() > r.right * 3 / 4) {
- if (mRemoveListener != null) {
- mRemoveListener.remove(mSrcDragPos);
- }
- unExpandViews(true);
- } else {
- if (mDropListener != null && mDragPos >= 0 && mDragPos < getCount()) {
- mDropListener.drop(mSrcDragPos, mDragPos);
- }
- unExpandViews(false);
- }
- break;
-
- case MotionEvent.ACTION_DOWN:
- case MotionEvent.ACTION_MOVE:
- int x = (int) ev.getX();
- int y = (int) ev.getY();
- dragView(x, y);
- int itemnum = getItemForPosition(y);
- if (itemnum >= 0) {
- if (action == MotionEvent.ACTION_DOWN || itemnum != mDragPos) {
- if (mDragListener != null) {
- mDragListener.drag(mDragPos, itemnum);
- }
- mDragPos = itemnum;
- doExpansion();
- }
- int speed = 0;
- adjustScrollBounds(y);
- if (y > mLowerBound) {
- // scroll the list up a bit
- if (getLastVisiblePosition() < getCount() - 1) {
- speed = y > (mHeight + mLowerBound) / 2 ? 16 : 4;
- } else {
- speed = 1;
- }
- } else if (y < mUpperBound) {
- // scroll the list down a bit
- speed = y < mUpperBound / 2 ? -16 : -4;
- if (getFirstVisiblePosition() == 0
- && getChildAt(0).getTop() >= getPaddingTop()) {
- // if we're already at the top, don't try to scroll, because
- // it causes the framework to do some extra drawing that messes
- // up our animation
- speed = 0;
- }
- }
- if (speed != 0) {
- smoothScrollBy(speed, 30);
- }
- }
- break;
- }
- return true;
- }
- return super.onTouchEvent(ev);
- }
-
- private void startDragging(Bitmap bm, int x, int y) {
- stopDragging();
-
- mWindowParams = new WindowManager.LayoutParams();
- mWindowParams.gravity = Gravity.TOP | Gravity.LEFT;
- mWindowParams.x = x - mDragPointX + mXOffset;
- mWindowParams.y = y - mDragPointY + mYOffset;
-
- mWindowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
- mWindowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
- mWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
- | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
- | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
- mWindowParams.format = PixelFormat.TRANSLUCENT;
- mWindowParams.windowAnimations = 0;
-
- Context context = getContext();
- ImageView v = new ImageView(context);
- // int backGroundColor = context.getResources().getColor(R.color.dragndrop_background);
- // v.setBackgroundColor(backGroundColor);
- v.setBackgroundResource(R.drawable.playlist_tile_drag);
- v.setPadding(0, 0, 0, 0);
- v.setImageBitmap(bm);
- mDragBitmap = bm;
-
- mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- mWindowManager.addView(v, mWindowParams);
- mDragView = v;
- }
-
- private void dragView(int x, int y) {
- if (mRemoveMode == SLIDE) {
- float alpha = 1.0f;
- int width = mDragView.getWidth();
- if (x > width / 2) {
- alpha = ((float) (width - x)) / (width / 2);
- }
- mWindowParams.alpha = alpha;
- }
-
- if (mRemoveMode == FLING || mRemoveMode == TRASH) {
- mWindowParams.x = x - mDragPointX + mXOffset;
- } else {
- mWindowParams.x = 0;
- }
- mWindowParams.y = y - mDragPointY + mYOffset;
- mWindowManager.updateViewLayout(mDragView, mWindowParams);
-
- if (mTrashcan != null) {
- int width = mDragView.getWidth();
- if (y > getHeight() * 3 / 4) {
- mTrashcan.setLevel(2);
- } else if (width > 0 && x > width / 4) {
- mTrashcan.setLevel(1);
- } else {
- mTrashcan.setLevel(0);
- }
- }
- }
-
- private void stopDragging() {
- if (mDragView != null) {
- mDragView.setVisibility(GONE);
- WindowManager wm =
- (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
- wm.removeView(mDragView);
- mDragView.setImageDrawable(null);
- mDragView = null;
- }
- if (mDragBitmap != null) {
- mDragBitmap.recycle();
- mDragBitmap = null;
- }
- if (mTrashcan != null) {
- mTrashcan.setLevel(0);
- }
- }
-
- public void setTrashcan(Drawable trash) {
- mTrashcan = trash;
- mRemoveMode = TRASH;
- }
-
- public void setDragListener(DragListener l) {
- mDragListener = l;
- }
-
- public void setDropListener(DropListener l) {
- mDropListener = l;
- }
-
- public void setRemoveListener(RemoveListener l) {
- mRemoveListener = l;
- }
-
- public interface DragListener { void drag(int from, int to); }
- public interface DropListener { void drop(int from, int to); }
- public interface RemoveListener { void remove(int which); }
-}
diff --git a/src/com/android/music/TrackBrowserActivity.java b/src/com/android/music/TrackBrowserActivity.java
deleted file mode 100644
index 7fb41b4..0000000
--- a/src/com/android/music/TrackBrowserActivity.java
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music;
-
-import android.app.Activity;
-import android.app.ListActivity;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Color;
-import android.graphics.drawable.Drawable;
-import android.media.AudioManager;
-import android.media.MediaDescription;
-import android.media.MediaMetadata;
-import android.media.browse.MediaBrowser;
-import android.media.session.MediaController;
-import android.media.session.MediaSession;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.widget.*;
-import com.android.music.utils.LogHelper;
-import com.android.music.utils.MediaIDHelper;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/*
-This activity shows when there is a need for
- 1. Songs tab [withtab = true]
- 2. Browse songs within an album [withtab = false]
- 3. Browse songs within a playlist [withtab = false]
- 4. Browse songs within now playing queue [withtab = false]
- */
-public class TrackBrowserActivity extends ListActivity {
- private static final String TAG = LogHelper.makeLogTag(TrackBrowserActivity.class);
- private static final MediaBrowser.MediaItem DEFAULT_PARENT_ITEM =
- new MediaBrowser.MediaItem(new MediaDescription.Builder()
- .setMediaId(MediaIDHelper.MEDIA_ID_MUSICS_BY_SONG)
- .setTitle("Songs")
- .build(),
- MediaBrowser.MediaItem.FLAG_BROWSABLE);
-
- // Underlining ListView of this Activity
- private ListView mTrackList;
- // The mediaId to be used for subscribing for children using the MediaBrowser.
- private MediaBrowser.MediaItem mParentItem;
- private MediaBrowser mMediaBrowser;
- private TrackBrowseAdapter mBrowseListAdapter;
- private boolean mWithTabs;
-
- /**
- * Called when the activity is first created.
- */
- @Override
- public void onCreate(Bundle icicle) {
- Log.d(TAG, "onCreate()");
- super.onCreate(icicle);
- // Process past states
- Intent intent = getIntent();
- if (icicle != null) {
- LogHelper.d(TAG, "Launch by saved instance state");
- mParentItem = icicle.getParcelable(MusicUtils.TAG_PARENT_ITEM);
- mWithTabs = icicle.getBoolean(MusicUtils.TAG_WITH_TABS);
- MusicUtils.updateNowPlaying(this);
- } else if (intent != null) {
- LogHelper.d(TAG, "Launch by intent");
- mParentItem = intent.getParcelableExtra(MusicUtils.TAG_PARENT_ITEM);
- mWithTabs = intent.getBooleanExtra(MusicUtils.TAG_WITH_TABS, false);
- }
- if (mParentItem == null) {
- LogHelper.d(TAG, "Launch by default parameters");
- mParentItem = DEFAULT_PARENT_ITEM;
- mWithTabs = true;
- }
- if (mWithTabs) {
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- }
- setTitle(mParentItem.getDescription().getTitle());
- setVolumeControlStream(AudioManager.STREAM_MUSIC);
-
- // Init layout
- LogHelper.d(TAG, "init layout");
- setContentView(R.layout.media_picker_activity);
- MusicUtils.updateButtonBar(this, R.id.songtab);
-
- // Init the ListView
- Log.d(TAG, "Creating ListView");
- mTrackList = getListView();
- mTrackList.setCacheColorHint(0);
- mTrackList.setTextFilterEnabled(true);
- mBrowseListAdapter = (TrackBrowseAdapter) getLastNonConfigurationInstance();
- if (mBrowseListAdapter == null) {
- mBrowseListAdapter = new TrackBrowseAdapter(this, R.layout.track_list_item);
- }
- setListAdapter(mBrowseListAdapter);
- // don't set the album art until after the view has been layed out
- mTrackList.post(new Runnable() {
- public void run() {
- mTrackList.setBackgroundColor(Color.WHITE);
- mTrackList.setCacheColorHint(0);
- }
- });
-
- // Create media browser
- Log.d(TAG, "Creating MediaBrowser");
- mMediaBrowser = new MediaBrowser(this, new ComponentName(this, MediaPlaybackService.class),
- mConnectionCallback, null);
- }
-
- @Override
- public void onStart() {
- Log.d(TAG, "onStart()");
- super.onStart();
- mMediaBrowser.connect();
- }
-
- @Override
- public void onStop() {
- Log.d(TAG, "onStop()");
- super.onStop();
- mMediaBrowser.disconnect();
- }
-
- @Override
- public void onDestroy() {
- Log.d(TAG, "onDestroy()");
- ListView lv = getListView();
- // Because we pass the adapter to the next activity, we need to make
- // sure it doesn't keep a reference to this activity. We can do this
- // by clearing its DatasetObservers, which setListAdapter(null) does.
- setListAdapter(null);
- mBrowseListAdapter = null;
- super.onDestroy();
- }
-
- @Override
- public void onResume() {
- Log.d(TAG, "onResume()");
- super.onResume();
- }
-
- @Override
- public void onPause() {
- Log.d(TAG, "onPause()");
- super.onPause();
- }
-
- @Override
- public void onSaveInstanceState(Bundle outcicle) {
- outcicle.putParcelable(MusicUtils.TAG_PARENT_ITEM, mParentItem);
- outcicle.putBoolean(MusicUtils.TAG_WITH_TABS, mWithTabs);
- super.onSaveInstanceState(outcicle);
- }
-
- private MediaBrowser.SubscriptionCallback mSubscriptionCallback =
- new MediaBrowser.SubscriptionCallback() {
-
- @Override
- public void onChildrenLoaded(
- String parentId, List<MediaBrowser.MediaItem> children) {
- mBrowseListAdapter.clear();
- mBrowseListAdapter.notifyDataSetInvalidated();
- for (MediaBrowser.MediaItem item : children) {
- mBrowseListAdapter.add(item);
- }
- mBrowseListAdapter.notifyDataSetChanged();
- }
-
- @Override
- public void onError(String id) {
- Toast.makeText(getApplicationContext(), R.string.error_loading_media,
- Toast.LENGTH_LONG)
- .show();
- }
- };
-
- private MediaBrowser.ConnectionCallback mConnectionCallback =
- new MediaBrowser.ConnectionCallback() {
- @Override
- public void onConnected() {
- Log.d(TAG, "onConnected: session token " + mMediaBrowser.getSessionToken());
- mMediaBrowser.subscribe(mParentItem.getMediaId(), mSubscriptionCallback);
- if (mMediaBrowser.getSessionToken() == null) {
- throw new IllegalArgumentException("No Session token");
- }
- MediaController mediaController = new MediaController(
- TrackBrowserActivity.this, mMediaBrowser.getSessionToken());
- mediaController.registerCallback(mMediaControllerCallback);
- TrackBrowserActivity.this.setMediaController(mediaController);
- if (mediaController.getMetadata() != null && mWithTabs) {
- MusicUtils.updateNowPlaying(TrackBrowserActivity.this);
- }
- }
-
- @Override
- public void onConnectionFailed() {
- Log.d(TAG, "onConnectionFailed");
- }
-
- @Override
- public void onConnectionSuspended() {
- Log.d(TAG, "onConnectionSuspended");
- TrackBrowserActivity.this.setMediaController(null);
- }
- };
-
- private MediaController.Callback mMediaControllerCallback = new MediaController.Callback() {
- @Override
- public void onMetadataChanged(MediaMetadata metadata) {
- super.onMetadataChanged(metadata);
- if (mWithTabs) {
- MusicUtils.updateNowPlaying(TrackBrowserActivity.this);
- }
- if (mBrowseListAdapter != null) {
- mBrowseListAdapter.notifyDataSetChanged();
- }
- }
- };
-
- // An adapter for showing the list of browsed MediaItem's
- private static class TrackBrowseAdapter extends ArrayAdapter<MediaBrowser.MediaItem> {
- private int mLayoutId;
- private final Drawable mNowPlayingOverlay;
- private Activity mActivity;
-
- static class ViewHolder {
- TextView line1;
- TextView line2;
- TextView duration;
- ImageView play_indicator;
- }
-
- TrackBrowseAdapter(Activity activity, int layout) {
- super(activity, layout, new ArrayList<>());
- mLayoutId = layout;
- mNowPlayingOverlay = activity.getResources().getDrawable(
- R.drawable.indicator_ic_mp_playing_list, activity.getTheme());
- mActivity = activity;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- Log.d(TAG, "getView()");
- if (convertView == null) {
- convertView = LayoutInflater.from(getContext()).inflate(mLayoutId, parent, false);
- ImageView iv = (ImageView) convertView.findViewById(R.id.icon);
- iv.setVisibility(View.GONE);
- ViewHolder vh = new ViewHolder();
- vh.line1 = (TextView) convertView.findViewById(R.id.line1);
- vh.line2 = (TextView) convertView.findViewById(R.id.line2);
- vh.duration = (TextView) convertView.findViewById(R.id.duration);
- vh.play_indicator = (ImageView) convertView.findViewById(R.id.play_indicator);
- convertView.setTag(vh);
- }
- ViewHolder holder = (ViewHolder) convertView.getTag();
- MediaBrowser.MediaItem item = getItem(position);
- Log.d(TAG, "title: " + item.getDescription().getTitle());
- holder.line1.setText(item.getDescription().getTitle());
- Log.d(TAG, "artist: " + item.getDescription().getSubtitle());
- holder.line2.setText(item.getDescription().getSubtitle());
- long duration =
- item.getDescription().getExtras().getLong(MediaMetadata.METADATA_KEY_DURATION);
- LogHelper.d(TAG, "duration: ", duration);
- holder.duration.setText(MusicUtils.makeTimeString(getContext(), duration / 1000));
- MediaController mediaController = mActivity.getMediaController();
- if (mediaController == null) {
- holder.play_indicator.setImageDrawable(null);
- return convertView;
- }
- MediaMetadata metadata = mediaController.getMetadata();
- if (metadata == null) {
- holder.play_indicator.setImageDrawable(null);
- return convertView;
- }
- if (item.getDescription().getMediaId().endsWith(
- metadata.getString(MediaMetadata.METADATA_KEY_MEDIA_ID))) {
- holder.play_indicator.setImageDrawable(mNowPlayingOverlay);
- } else {
- holder.play_indicator.setImageDrawable(null);
- }
- return convertView;
- }
- }
-
- @Override
- public Object onRetainNonConfigurationInstance() {
- TrackBrowseAdapter a = mBrowseListAdapter;
- return a;
- }
-
- @Override
- protected void onListItemClick(ListView l, View v, int position, long id) {
- Log.d(TAG, "onListItemClick at position " + position + ", id " + id);
- MediaBrowser.MediaItem item = mBrowseListAdapter.getItem(position);
- if (item.isPlayable()) {
- getMediaController().getTransportControls().playFromMediaId(item.getMediaId(), null);
- }
- }
-}
diff --git a/src/com/android/music/VerticalTextSpinner.java b/src/com/android/music/VerticalTextSpinner.java
deleted file mode 100644
index c2d896b..0000000
--- a/src/com/android/music/VerticalTextSpinner.java
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.NinePatchDrawable;
-import android.text.TextPaint;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.View;
-
-public class VerticalTextSpinner extends View {
- private static final int SELECTOR_ARROW_HEIGHT = 15;
-
- private static int TEXT_SPACING;
- private static int TEXT_MARGIN_RIGHT;
- private static int TEXT_SIZE;
- private static int TEXT1_Y;
- private static int TEXT2_Y;
- private static int TEXT3_Y;
- private static int TEXT4_Y;
- private static int TEXT5_Y;
- private static int SCROLL_DISTANCE;
-
- private static final int SCROLL_MODE_NONE = 0;
- private static final int SCROLL_MODE_UP = 1;
- private static final int SCROLL_MODE_DOWN = 2;
-
- private static final long DEFAULT_SCROLL_INTERVAL_MS = 400;
- private static final int MIN_ANIMATIONS = 4;
-
- private final Drawable mBackgroundFocused;
- private final Drawable mSelectorFocused;
- private final Drawable mSelectorNormal;
- private final int mSelectorDefaultY;
- private final int mSelectorMinY;
- private final int mSelectorMaxY;
- private final int mSelectorHeight;
- private final TextPaint mTextPaintDark;
- private final TextPaint mTextPaintLight;
-
- private int mSelectorY;
- private Drawable mSelector;
- private int mDownY;
- private boolean isDraggingSelector;
- private int mScrollMode;
- private long mScrollInterval;
- private boolean mIsAnimationRunning;
- private boolean mStopAnimation;
- private boolean mWrapAround = true;
-
- private int mTotalAnimatedDistance;
- private int mNumberOfAnimations;
- private long mDelayBetweenAnimations;
- private int mDistanceOfEachAnimation;
-
- private String[] mTextList;
- private int mCurrentSelectedPos;
- private OnChangedListener mListener;
-
- private String mText1;
- private String mText2;
- private String mText3;
- private String mText4;
- private String mText5;
-
- public interface OnChangedListener {
- void onChanged(VerticalTextSpinner spinner, int oldPos, int newPos, String[] items);
- }
-
- public VerticalTextSpinner(Context context) {
- this(context, null);
- }
-
- public VerticalTextSpinner(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public VerticalTextSpinner(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- float scale = getResources().getDisplayMetrics().density;
- TEXT_SPACING = (int) (18 * scale);
- TEXT_MARGIN_RIGHT = (int) (25 * scale);
- TEXT_SIZE = (int) (22 * scale);
- SCROLL_DISTANCE = TEXT_SIZE + TEXT_SPACING;
- TEXT1_Y = (TEXT_SIZE * (-2 + 2)) + (TEXT_SPACING * (-2 + 1));
- TEXT2_Y = (TEXT_SIZE * (-1 + 2)) + (TEXT_SPACING * (-1 + 1));
- TEXT3_Y = (TEXT_SIZE * (0 + 2)) + (TEXT_SPACING * (0 + 1));
- TEXT4_Y = (TEXT_SIZE * (1 + 2)) + (TEXT_SPACING * (1 + 1));
- TEXT5_Y = (TEXT_SIZE * (2 + 2)) + (TEXT_SPACING * (2 + 1));
-
- mBackgroundFocused = context.getResources().getDrawable(R.drawable.pickerbox_background);
- mSelectorFocused = context.getResources().getDrawable(R.drawable.pickerbox_selected);
- mSelectorNormal = context.getResources().getDrawable(R.drawable.pickerbox_unselected);
-
- mSelectorHeight = mSelectorFocused.getIntrinsicHeight();
- mSelectorDefaultY = (mBackgroundFocused.getIntrinsicHeight() - mSelectorHeight) / 2;
- mSelectorMinY = 0;
- mSelectorMaxY = mBackgroundFocused.getIntrinsicHeight() - mSelectorHeight;
-
- mSelector = mSelectorNormal;
- mSelectorY = mSelectorDefaultY;
-
- mTextPaintDark = new TextPaint(Paint.ANTI_ALIAS_FLAG);
- mTextPaintDark.setTextSize(TEXT_SIZE);
- mTextPaintDark.setColor(
- context.getResources().getColor(android.R.color.primary_text_light));
-
- mTextPaintLight = new TextPaint(Paint.ANTI_ALIAS_FLAG);
- mTextPaintLight.setTextSize(TEXT_SIZE);
- mTextPaintLight.setColor(
- context.getResources().getColor(android.R.color.secondary_text_dark));
-
- mScrollMode = SCROLL_MODE_NONE;
- mScrollInterval = DEFAULT_SCROLL_INTERVAL_MS;
- calculateAnimationValues();
- }
-
- public void setOnChangeListener(OnChangedListener listener) {
- mListener = listener;
- }
-
- public void setItems(String[] textList) {
- mTextList = textList;
- calculateTextPositions();
- }
-
- public void setSelectedPos(int selectedPos) {
- mCurrentSelectedPos = selectedPos;
- calculateTextPositions();
- postInvalidate();
- }
-
- public void setScrollInterval(long interval) {
- mScrollInterval = interval;
- calculateAnimationValues();
- }
-
- public void setWrapAround(boolean wrap) {
- mWrapAround = wrap;
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- /* This is a bit confusing, when we get the key event
- * DPAD_DOWN we actually roll the spinner up. When the
- * key event is DPAD_UP we roll the spinner down.
- */
- if ((keyCode == KeyEvent.KEYCODE_DPAD_UP) && canScrollDown()) {
- mScrollMode = SCROLL_MODE_DOWN;
- scroll();
- mStopAnimation = true;
- return true;
- } else if ((keyCode == KeyEvent.KEYCODE_DPAD_DOWN) && canScrollUp()) {
- mScrollMode = SCROLL_MODE_UP;
- scroll();
- mStopAnimation = true;
- return true;
- }
- return super.onKeyDown(keyCode, event);
- }
-
- private boolean canScrollDown() {
- return (mCurrentSelectedPos > 0) || mWrapAround;
- }
-
- private boolean canScrollUp() {
- return ((mCurrentSelectedPos < (mTextList.length - 1)) || mWrapAround);
- }
-
- @Override
- protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
- if (gainFocus) {
- setBackgroundDrawable(mBackgroundFocused);
- mSelector = mSelectorFocused;
- } else {
- setBackgroundDrawable(null);
- mSelector = mSelectorNormal;
- mSelectorY = mSelectorDefaultY;
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- final int action = event.getAction();
- final int y = (int) event.getY();
-
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- requestFocus();
- mDownY = y;
- isDraggingSelector =
- (y >= mSelectorY) && (y <= (mSelectorY + mSelector.getIntrinsicHeight()));
- break;
-
- case MotionEvent.ACTION_MOVE:
- if (isDraggingSelector) {
- int top = mSelectorDefaultY + (y - mDownY);
- if (top <= mSelectorMinY && canScrollDown()) {
- mSelectorY = mSelectorMinY;
- mStopAnimation = false;
- if (mScrollMode != SCROLL_MODE_DOWN) {
- mScrollMode = SCROLL_MODE_DOWN;
- scroll();
- }
- } else if (top >= mSelectorMaxY && canScrollUp()) {
- mSelectorY = mSelectorMaxY;
- mStopAnimation = false;
- if (mScrollMode != SCROLL_MODE_UP) {
- mScrollMode = SCROLL_MODE_UP;
- scroll();
- }
- } else {
- mSelectorY = top;
- mStopAnimation = true;
- }
- }
- break;
-
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL:
- default:
- mSelectorY = mSelectorDefaultY;
- mStopAnimation = true;
- invalidate();
- break;
- }
- return true;
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- /* The bounds of the selector */
- final int selectorLeft = 0;
- final int selectorTop = mSelectorY;
- final int selectorRight = getWidth();
- final int selectorBottom = mSelectorY + mSelectorHeight;
-
- /* Draw the selector */
- mSelector.setBounds(selectorLeft, selectorTop, selectorRight, selectorBottom);
- mSelector.draw(canvas);
-
- if (mTextList == null) {
- /* We're not setup with values so don't draw anything else */
- return;
- }
-
- final TextPaint textPaintDark = mTextPaintDark;
- if (hasFocus()) {
- /* The bounds of the top area where the text should be light */
- final int topLeft = 0;
- final int topTop = 0;
- final int topRight = selectorRight;
- final int topBottom = selectorTop + SELECTOR_ARROW_HEIGHT;
-
- /* Assign a bunch of local finals for performance */
- final String text1 = mText1;
- final String text2 = mText2;
- final String text3 = mText3;
- final String text4 = mText4;
- final String text5 = mText5;
- final TextPaint textPaintLight = mTextPaintLight;
-
- /*
- * Draw the 1st, 2nd and 3rd item in light only, clip it so it only
- * draws in the area above the selector
- */
- canvas.save();
- canvas.clipRect(topLeft, topTop, topRight, topBottom);
- drawText(canvas, text1, TEXT1_Y + mTotalAnimatedDistance, textPaintLight);
- drawText(canvas, text2, TEXT2_Y + mTotalAnimatedDistance, textPaintLight);
- drawText(canvas, text3, TEXT3_Y + mTotalAnimatedDistance, textPaintLight);
- canvas.restore();
-
- /*
- * Draw the 2nd, 3rd and 4th clipped to the selector bounds in dark
- * paint
- */
- canvas.save();
- canvas.clipRect(selectorLeft, selectorTop + SELECTOR_ARROW_HEIGHT, selectorRight,
- selectorBottom - SELECTOR_ARROW_HEIGHT);
- drawText(canvas, text2, TEXT2_Y + mTotalAnimatedDistance, textPaintDark);
- drawText(canvas, text3, TEXT3_Y + mTotalAnimatedDistance, textPaintDark);
- drawText(canvas, text4, TEXT4_Y + mTotalAnimatedDistance, textPaintDark);
- canvas.restore();
-
- /* The bounds of the bottom area where the text should be light */
- final int bottomLeft = 0;
- final int bottomTop = selectorBottom - SELECTOR_ARROW_HEIGHT;
- final int bottomRight = selectorRight;
- final int bottomBottom = getMeasuredHeight();
-
- /*
- * Draw the 3rd, 4th and 5th in white text, clip it so it only draws
- * in the area below the selector.
- */
- canvas.save();
- canvas.clipRect(bottomLeft, bottomTop, bottomRight, bottomBottom);
- drawText(canvas, text3, TEXT3_Y + mTotalAnimatedDistance, textPaintLight);
- drawText(canvas, text4, TEXT4_Y + mTotalAnimatedDistance, textPaintLight);
- drawText(canvas, text5, TEXT5_Y + mTotalAnimatedDistance, textPaintLight);
- canvas.restore();
-
- } else {
- drawText(canvas, mText3, TEXT3_Y, textPaintDark);
- }
- if (mIsAnimationRunning) {
- if ((Math.abs(mTotalAnimatedDistance) + mDistanceOfEachAnimation) > SCROLL_DISTANCE) {
- mTotalAnimatedDistance = 0;
- if (mScrollMode == SCROLL_MODE_UP) {
- int oldPos = mCurrentSelectedPos;
- int newPos = getNewIndex(1);
- if (newPos >= 0) {
- mCurrentSelectedPos = newPos;
- if (mListener != null) {
- mListener.onChanged(this, oldPos, mCurrentSelectedPos, mTextList);
- }
- }
- if (newPos < 0 || ((newPos >= mTextList.length - 1) && !mWrapAround)) {
- mStopAnimation = true;
- }
- calculateTextPositions();
- } else if (mScrollMode == SCROLL_MODE_DOWN) {
- int oldPos = mCurrentSelectedPos;
- int newPos = getNewIndex(-1);
- if (newPos >= 0) {
- mCurrentSelectedPos = newPos;
- if (mListener != null) {
- mListener.onChanged(this, oldPos, mCurrentSelectedPos, mTextList);
- }
- }
- if (newPos < 0 || (newPos == 0 && !mWrapAround)) {
- mStopAnimation = true;
- }
- calculateTextPositions();
- }
- if (mStopAnimation) {
- final int previousScrollMode = mScrollMode;
-
- /* No longer scrolling, we wait till the current animation
- * completes then we stop.
- */
- mIsAnimationRunning = false;
- mStopAnimation = false;
- mScrollMode = SCROLL_MODE_NONE;
-
- /* If the current selected item is an empty string
- * scroll past it.
- */
- if ("".equals(mTextList[mCurrentSelectedPos])) {
- mScrollMode = previousScrollMode;
- scroll();
- mStopAnimation = true;
- }
- }
- } else {
- if (mScrollMode == SCROLL_MODE_UP) {
- mTotalAnimatedDistance -= mDistanceOfEachAnimation;
- } else if (mScrollMode == SCROLL_MODE_DOWN) {
- mTotalAnimatedDistance += mDistanceOfEachAnimation;
- }
- }
- if (mDelayBetweenAnimations > 0) {
- postInvalidateDelayed(mDelayBetweenAnimations);
- } else {
- invalidate();
- }
- }
- }
-
- /**
- * Called every time the text items or current position
- * changes. We calculate store we don't have to calculate
- * onDraw.
- */
- private void calculateTextPositions() {
- mText1 = getTextToDraw(-2);
- mText2 = getTextToDraw(-1);
- mText3 = getTextToDraw(0);
- mText4 = getTextToDraw(1);
- mText5 = getTextToDraw(2);
- }
-
- private String getTextToDraw(int offset) {
- int index = getNewIndex(offset);
- if (index < 0) {
- return "";
- }
- return mTextList[index];
- }
-
- private int getNewIndex(int offset) {
- int index = mCurrentSelectedPos + offset;
- if (index < 0) {
- if (mWrapAround) {
- index += mTextList.length;
- } else {
- return -1;
- }
- } else if (index >= mTextList.length) {
- if (mWrapAround) {
- index -= mTextList.length;
- } else {
- return -1;
- }
- }
- return index;
- }
-
- private void scroll() {
- if (mIsAnimationRunning) {
- return;
- }
- mTotalAnimatedDistance = 0;
- mIsAnimationRunning = true;
- invalidate();
- }
-
- private void calculateAnimationValues() {
- mNumberOfAnimations = (int) mScrollInterval / SCROLL_DISTANCE;
- if (mNumberOfAnimations < MIN_ANIMATIONS) {
- mNumberOfAnimations = MIN_ANIMATIONS;
- mDistanceOfEachAnimation = SCROLL_DISTANCE / mNumberOfAnimations;
- mDelayBetweenAnimations = 0;
- } else {
- mDistanceOfEachAnimation = SCROLL_DISTANCE / mNumberOfAnimations;
- mDelayBetweenAnimations = mScrollInterval / mNumberOfAnimations;
- }
- }
-
- private void drawText(Canvas canvas, String text, int y, TextPaint paint) {
- int width = (int) paint.measureText(text);
- int x = getMeasuredWidth() - width - TEXT_MARGIN_RIGHT;
- canvas.drawText(text, x, y, paint);
- }
-
- public int getCurrentSelectedPos() {
- return mCurrentSelectedPos;
- }
-}
diff --git a/src/com/android/music/utils/AlbumArtCache.java b/src/com/android/music/utils/AlbumArtCache.java
deleted file mode 100644
index 7021021..0000000
--- a/src/com/android/music/utils/AlbumArtCache.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music.utils;
-
-import android.graphics.Bitmap;
-import android.os.AsyncTask;
-import android.util.LruCache;
-
-import java.io.IOException;
-
-/**
- * Implements a basic cache of album arts, with async loading support.
- */
-public final class AlbumArtCache {
- private static final String TAG = LogHelper.makeLogTag(AlbumArtCache.class);
-
- private static final int MAX_ALBUM_ART_CACHE_SIZE = 12 * 1024 * 1024; // 12 MB
- private static final int MAX_ART_WIDTH = 800; // pixels
- private static final int MAX_ART_HEIGHT = 480; // pixels
-
- // Resolution reasonable for carrying around as an icon (generally in
- // MediaDescription.getIconBitmap). This should not be bigger than necessary, because
- // the MediaDescription object should be lightweight. If you set it too high and try to
- // serialize the MediaDescription, you may get FAILED BINDER TRANSACTION errors.
- private static final int MAX_ART_WIDTH_ICON = 128; // pixels
- private static final int MAX_ART_HEIGHT_ICON = 128; // pixels
-
- private static final int BIG_BITMAP_INDEX = 0;
- private static final int ICON_BITMAP_INDEX = 1;
-
- private final LruCache<String, Bitmap[]> mCache;
-
- private static final AlbumArtCache sInstance = new AlbumArtCache();
-
- public static AlbumArtCache getInstance() {
- return sInstance;
- }
-
- private AlbumArtCache() {
- // Holds no more than MAX_ALBUM_ART_CACHE_SIZE bytes, bounded by maxmemory/4 and
- // Integer.MAX_VALUE:
- int maxSize = Math.min(MAX_ALBUM_ART_CACHE_SIZE,
- (int) (Math.min(Integer.MAX_VALUE, Runtime.getRuntime().maxMemory() / 4)));
- mCache = new LruCache<String, Bitmap[]>(maxSize) {
- @Override
- protected int sizeOf(String key, Bitmap[] value) {
- return value[BIG_BITMAP_INDEX].getByteCount()
- + value[ICON_BITMAP_INDEX].getByteCount();
- }
- };
- }
-
- public Bitmap getBigImage(String artUrl) {
- Bitmap[] result = mCache.get(artUrl);
- return result == null ? null : result[BIG_BITMAP_INDEX];
- }
-
- public Bitmap getIconImage(String artUrl) {
- Bitmap[] result = mCache.get(artUrl);
- return result == null ? null : result[ICON_BITMAP_INDEX];
- }
-
- public void fetch(final String artUrl, final FetchListener listener) {
- // WARNING: for the sake of simplicity, simultaneous multi-thread fetch requests
- // are not handled properly: they may cause redundant costly operations, like HTTP
- // requests and bitmap rescales. For production-level apps, we recommend you use
- // a proper image loading library, like Glide.
- Bitmap[] bitmap = mCache.get(artUrl);
- if (bitmap != null) {
- LogHelper.d(TAG, "getOrFetch: album art is in cache, using it", artUrl);
- listener.onFetched(artUrl, bitmap[BIG_BITMAP_INDEX], bitmap[ICON_BITMAP_INDEX]);
- return;
- }
- LogHelper.d(TAG, "getOrFetch: starting asynctask to fetch ", artUrl);
-
- new AsyncTask<Void, Void, Bitmap[]>() {
- @Override
- protected Bitmap[] doInBackground(Void[] objects) {
- Bitmap[] bitmaps;
- try {
- Bitmap bitmap = BitmapHelper.fetchAndRescaleBitmap(
- artUrl, MAX_ART_WIDTH, MAX_ART_HEIGHT);
- Bitmap icon = BitmapHelper.scaleBitmap(
- bitmap, MAX_ART_WIDTH_ICON, MAX_ART_HEIGHT_ICON);
- bitmaps = new Bitmap[] {bitmap, icon};
- mCache.put(artUrl, bitmaps);
- } catch (IOException e) {
- return null;
- }
- LogHelper.d(TAG,
- "doInBackground: putting bitmap in cache. cache size=" + mCache.size());
- return bitmaps;
- }
-
- @Override
- protected void onPostExecute(Bitmap[] bitmaps) {
- if (bitmaps == null) {
- listener.onError(artUrl, new IllegalArgumentException("got null bitmaps"));
- } else {
- listener.onFetched(
- artUrl, bitmaps[BIG_BITMAP_INDEX], bitmaps[ICON_BITMAP_INDEX]);
- }
- }
- }
- .execute();
- }
-
- public static abstract class FetchListener {
- public abstract void onFetched(String artUrl, Bitmap bigImage, Bitmap iconImage);
- public void onError(String artUrl, Exception e) {
- LogHelper.e(TAG, e, "AlbumArtFetchListener: error while downloading " + artUrl);
- }
- }
-}
diff --git a/src/com/android/music/utils/BitmapHelper.java b/src/com/android/music/utils/BitmapHelper.java
deleted file mode 100644
index 5746233..0000000
--- a/src/com/android/music/utils/BitmapHelper.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.music.utils;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.HttpURLConnection;
-import java.net.URL;
-
-public class BitmapHelper {
- private static final String TAG = LogHelper.makeLogTag(BitmapHelper.class);
-
- // Max read limit that we allow our input stream to mark/reset.
- private static final int MAX_READ_LIMIT_PER_IMG = 1024 * 1024;
-
- public static Bitmap scaleBitmap(Bitmap src, int maxWidth, int maxHeight) {
- double scaleFactor = Math.min(
- ((double) maxWidth) / src.getWidth(), ((double) maxHeight) / src.getHeight());
- return Bitmap.createScaledBitmap(src, (int) (src.getWidth() * scaleFactor),
- (int) (src.getHeight() * scaleFactor), false);
- }
-
- public static Bitmap scaleBitmap(int scaleFactor, InputStream is) {
- // Get the dimensions of the bitmap
- BitmapFactory.Options bmOptions = new BitmapFactory.Options();
-
- // Decode the image file into a Bitmap sized to fill the View
- bmOptions.inJustDecodeBounds = false;
- bmOptions.inSampleSize = scaleFactor;
-
- return BitmapFactory.decodeStream(is, null, bmOptions);
- }
-
- public static int findScaleFactor(int targetW, int targetH, InputStream is) {
- // Get the dimensions of the bitmap
- BitmapFactory.Options bmOptions = new BitmapFactory.Options();
- bmOptions.inJustDecodeBounds = true;
- BitmapFactory.decodeStream(is, null, bmOptions);
- int actualW = bmOptions.outWidth;
- int actualH = bmOptions.outHeight;
-
- // Determine how much to scale down the image
- return Math.min(actualW / targetW, actualH / targetH);
- }
-
- @SuppressWarnings("SameParameterValue")
- public static Bitmap fetchAndRescaleBitmap(String uri, int width, int height)
- throws IOException {
- URL url = new URL(uri);
- BufferedInputStream is = null;
- try {
- HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
- is = new BufferedInputStream(urlConnection.getInputStream());
- is.mark(MAX_READ_LIMIT_PER_IMG);
- int scaleFactor = findScaleFactor(width, height, is);
- LogHelper.d(TAG, "Scaling bitmap ", uri, " by factor ", scaleFactor, " to support ",
- width, "x", height, "requested dimension");
- is.reset();
- return scaleBitmap(scaleFactor, is);
- } finally {
- if (is != null) {
- is.close();
- }
- }
- }
-}
diff --git a/src/com/android/music/utils/CheckableRelativeLayout.java b/src/com/android/music/utils/CheckableRelativeLayout.java
deleted file mode 100644
index 125fecb..0000000
--- a/src/com/android/music/utils/CheckableRelativeLayout.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music.utils;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.Checkable;
-import android.widget.RelativeLayout;
-
-/**
- * A special variation of RelativeLayout that can be used as a checkable object.
- * This allows it to be used as the top-level view of a list view item, which
- * also supports checking. Otherwise, it works identically to a RelativeLayout.
- */
-public class CheckableRelativeLayout extends RelativeLayout implements Checkable {
- private boolean mChecked;
-
- private static final int[] CHECKED_STATE_SET = {android.R.attr.state_checked};
-
- public CheckableRelativeLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected int[] onCreateDrawableState(int extraSpace) {
- final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
- if (isChecked()) {
- mergeDrawableStates(drawableState, CHECKED_STATE_SET);
- }
- return drawableState;
- }
-
- public void toggle() {
- setChecked(!mChecked);
- }
-
- public boolean isChecked() {
- return mChecked;
- }
-
- public void setChecked(boolean checked) {
- if (mChecked != checked) {
- mChecked = checked;
- refreshDrawableState();
- }
- }
-}
diff --git a/src/com/android/music/utils/LogHelper.java b/src/com/android/music/utils/LogHelper.java
deleted file mode 100644
index 3a0d2ee..0000000
--- a/src/com/android/music/utils/LogHelper.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.music.utils;
-
-import android.util.Log;
-
-public class LogHelper {
- private static final String LOG_PREFIX = "music_";
- private static final int LOG_PREFIX_LENGTH = LOG_PREFIX.length();
- private static final int MAX_LOG_TAG_LENGTH = 23;
- private static final boolean DEBUG = true;
-
- public static String makeLogTag(String str) {
- if (str.length() > MAX_LOG_TAG_LENGTH - LOG_PREFIX_LENGTH) {
- return LOG_PREFIX + str.substring(0, MAX_LOG_TAG_LENGTH - LOG_PREFIX_LENGTH - 1);
- }
-
- return LOG_PREFIX + str;
- }
-
- /**
- * Don't use this when obfuscating class names!
- */
- public static String makeLogTag(Class cls) {
- return makeLogTag(cls.getSimpleName());
- }
-
- public static void v(String tag, Object... messages) {
- // Only log VERBOSE if build type is DEBUG
- if (DEBUG) {
- log(tag, Log.VERBOSE, null, messages);
- }
- }
-
- public static void d(String tag, Object... messages) {
- // Only log DEBUG if build type is DEBUG
- if (DEBUG) {
- log(tag, Log.DEBUG, null, messages);
- }
- }
-
- public static void i(String tag, Object... messages) {
- log(tag, Log.INFO, null, messages);
- }
-
- public static void w(String tag, Object... messages) {
- log(tag, Log.WARN, null, messages);
- }
-
- public static void w(String tag, Throwable t, Object... messages) {
- log(tag, Log.WARN, t, messages);
- }
-
- public static void e(String tag, Object... messages) {
- log(tag, Log.ERROR, null, messages);
- }
-
- public static void e(String tag, Throwable t, Object... messages) {
- log(tag, Log.ERROR, t, messages);
- }
-
- public static void log(String tag, int level, Throwable t, Object... messages) {
- String message;
- if (t == null && messages != null && messages.length == 1) {
- // handle this common case without the extra cost of creating a stringbuffer:
- message = messages[0].toString();
- } else {
- StringBuilder sb = new StringBuilder();
- if (messages != null)
- for (Object m : messages) {
- sb.append(m);
- }
- if (t != null) {
- sb.append("\n").append(Log.getStackTraceString(t));
- }
- message = sb.toString();
- }
- Log.println(level, tag, message);
- }
-}
diff --git a/src/com/android/music/utils/MediaIDHelper.java b/src/com/android/music/utils/MediaIDHelper.java
deleted file mode 100644
index e991e4a..0000000
--- a/src/com/android/music/utils/MediaIDHelper.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music.utils;
-
-import java.util.Arrays;
-
-/**
- * Utility class to help on queue related tasks.
- */
-public class MediaIDHelper {
- private static final String TAG = "MediaIDHelper";
-
- // Media IDs used on browseable items of MediaBrowser
- public static final String MEDIA_ID_ROOT = "__ROOT__";
- public static final String MEDIA_ID_MUSICS_BY_ARTIST = "__BY_ARTIST__";
- public static final String MEDIA_ID_MUSICS_BY_ALBUM = "__BY_ALBUM__";
- public static final String MEDIA_ID_MUSICS_BY_SONG = "__BY_SONG__";
- public static final String MEDIA_ID_MUSICS_BY_PLAYLIST = "__BY_PLAYLIST__";
- public static final String MEDIA_ID_MUSICS_BY_SEARCH = "__BY_SEARCH__";
- public static final String MEDIA_ID_NOW_PLAYING = "__NOW_PLAYING__";
-
- private static final char CATEGORY_SEPARATOR = 31;
- private static final char LEAF_SEPARATOR = 30;
-
- public static String createMediaID(String musicID, String... categories) {
- // MediaIDs are of the form <categoryType>/<categoryValue>|<musicUniqueId>, to make it easy
- // to find the category (like genre) that a music was selected from, so we
- // can correctly build the playing queue. This is specially useful when
- // one music can appear in more than one list, like "by genre -> genre_1"
- // and "by artist -> artist_1".
- StringBuilder sb = new StringBuilder();
- if (categories != null && categories.length > 0) {
- sb.append(categories[0]);
- for (int i = 1; i < categories.length; i++) {
- sb.append(CATEGORY_SEPARATOR).append(categories[i]);
- }
- }
- if (musicID != null) {
- sb.append(LEAF_SEPARATOR).append(musicID);
- }
- return sb.toString();
- }
-
- public static String createBrowseCategoryMediaID(String categoryType, String categoryValue) {
- return categoryType + CATEGORY_SEPARATOR + categoryValue;
- }
-
- /**
- * Extracts unique musicID from the mediaID. mediaID is, by this sample's convention, a
- * concatenation of category (eg "by_genre"), categoryValue (eg "Classical") and unique
- * musicID. This is necessary so we know where the user selected the music from, when the music
- * exists in more than one music list, and thus we are able to correctly build the playing
- * queue.
- *
- * @param mediaID that contains the musicID
- * @return musicID
- */
- public static String extractMusicIDFromMediaID(String mediaID) {
- int pos = mediaID.indexOf(LEAF_SEPARATOR);
- if (pos >= 0) {
- return mediaID.substring(pos + 1);
- }
- return null;
- }
-
- /**
- * Extracts category and categoryValue from the mediaID. mediaID is, by this sample's
- * convention, a concatenation of category (eg "by_genre"), categoryValue (eg "Classical") and
- * mediaID. This is necessary so we know where the user selected the music from, when the music
- * exists in more than one music list, and thus we are able to correctly build the playing
- * queue.
- *
- * @param mediaID that contains a category and categoryValue.
- */
- public static String[] getHierarchy(String mediaID) {
- int pos = mediaID.indexOf(LEAF_SEPARATOR);
- if (pos >= 0) {
- mediaID = mediaID.substring(0, pos);
- }
- return mediaID.split(String.valueOf(CATEGORY_SEPARATOR));
- }
-
- public static String extractBrowseCategoryValueFromMediaID(String mediaID) {
- String[] hierarchy = getHierarchy(mediaID);
- if (hierarchy != null && hierarchy.length == 2) {
- return hierarchy[1];
- }
- return null;
- }
-
- private static boolean isBrowseable(String mediaID) {
- return mediaID.indexOf(LEAF_SEPARATOR) < 0;
- }
-
- public static String getParentMediaID(String mediaID) {
- String[] hierarchy = getHierarchy(mediaID);
- if (!isBrowseable(mediaID)) {
- return createMediaID(null, hierarchy);
- }
- if (hierarchy == null || hierarchy.length <= 1) {
- return MEDIA_ID_ROOT;
- }
- String[] parentHierarchy = Arrays.copyOf(hierarchy, hierarchy.length - 1);
- return createMediaID(null, parentHierarchy);
- }
-}
diff --git a/src/com/android/music/utils/MediaNotificationManager.java b/src/com/android/music/utils/MediaNotificationManager.java
deleted file mode 100644
index 65b9797..0000000
--- a/src/com/android/music/utils/MediaNotificationManager.java
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music.utils;
-
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Color;
-import android.media.MediaDescription;
-import android.media.MediaMetadata;
-import android.media.session.MediaController;
-import android.media.session.MediaSession;
-import android.media.session.PlaybackState;
-import android.service.media.MediaBrowserService;
-import android.util.Log;
-import com.android.music.MediaPlaybackService;
-import com.android.music.R;
-
-/**
- * Keeps track of a notification and updates it automatically for a given
- * MediaSession. Maintaining a visible notification (usually) guarantees that the music service
- * won't be killed during playback.
- */
-public class MediaNotificationManager extends BroadcastReceiver {
- private static final String TAG = LogHelper.makeLogTag(MediaNotificationManager.class);
-
- private static final int NOTIFICATION_ID = 412;
- private static final int REQUEST_CODE = 100;
-
- public static final String ACTION_PAUSE = "com.android.music.pause";
- public static final String ACTION_PLAY = "com.android.music.play";
- public static final String ACTION_PREV = "com.android.music.prev";
- public static final String ACTION_NEXT = "com.android.music.next";
-
- private final MediaPlaybackService mService;
- private MediaSession.Token mSessionToken;
- private MediaController mController;
- private MediaController.TransportControls mTransportControls;
-
- private PlaybackState mPlaybackState;
- private MediaMetadata mMetadata;
-
- private NotificationManager mNotificationManager;
-
- private PendingIntent mPauseIntent;
- private PendingIntent mPlayIntent;
- private PendingIntent mPreviousIntent;
- private PendingIntent mNextIntent;
-
- private int mNotificationColor;
-
- private boolean mStarted = false;
-
- public MediaNotificationManager(MediaPlaybackService service) {
- mService = service;
- updateSessionToken();
-
- mNotificationColor =
- ResourceHelper.getThemeColor(mService, android.R.attr.colorPrimary, Color.DKGRAY);
-
- mNotificationManager =
- (NotificationManager) mService.getSystemService(Context.NOTIFICATION_SERVICE);
-
- String pkg = mService.getPackageName();
- mPauseIntent = PendingIntent.getBroadcast(mService, REQUEST_CODE,
- new Intent(ACTION_PAUSE).setPackage(pkg), PendingIntent.FLAG_CANCEL_CURRENT);
- mPlayIntent = PendingIntent.getBroadcast(mService, REQUEST_CODE,
- new Intent(ACTION_PLAY).setPackage(pkg), PendingIntent.FLAG_CANCEL_CURRENT);
- mPreviousIntent = PendingIntent.getBroadcast(mService, REQUEST_CODE,
- new Intent(ACTION_PREV).setPackage(pkg), PendingIntent.FLAG_CANCEL_CURRENT);
- mNextIntent = PendingIntent.getBroadcast(mService, REQUEST_CODE,
- new Intent(ACTION_NEXT).setPackage(pkg), PendingIntent.FLAG_CANCEL_CURRENT);
-
- // Cancel all notifications to handle the case where the Service was killed and
- // restarted by the system.
- mNotificationManager.cancelAll();
- }
-
- /**
- * Posts the notification and starts tracking the session to keep it
- * updated. The notification will automatically be removed if the session is
- * destroyed before {@link #stopNotification} is called.
- */
- public void startNotification() {
- if (!mStarted) {
- mMetadata = mController.getMetadata();
- mPlaybackState = mController.getPlaybackState();
-
- // The notification must be updated after setting started to true
- Notification notification = createNotification();
- if (notification != null) {
- mController.registerCallback(mCb);
- IntentFilter filter = new IntentFilter();
- filter.addAction(ACTION_NEXT);
- filter.addAction(ACTION_PAUSE);
- filter.addAction(ACTION_PLAY);
- filter.addAction(ACTION_PREV);
- mService.registerReceiver(this, filter);
-
- mService.startForeground(NOTIFICATION_ID, notification);
- mStarted = true;
- }
- }
- }
-
- /**
- * Removes the notification and stops tracking the session. If the session
- * was destroyed this has no effect.
- */
- public void stopNotification() {
- if (mStarted) {
- mStarted = false;
- mController.unregisterCallback(mCb);
- try {
- mNotificationManager.cancel(NOTIFICATION_ID);
- mService.unregisterReceiver(this);
- } catch (IllegalArgumentException ex) {
- // ignore if the receiver is not registered.
- }
- mService.stopForeground(true);
- }
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- LogHelper.d(TAG, "Received intent with action " + action);
- switch (action) {
- case ACTION_PAUSE:
- mTransportControls.pause();
- break;
- case ACTION_PLAY:
- mTransportControls.play();
- break;
- case ACTION_NEXT:
- mTransportControls.skipToNext();
- break;
- case ACTION_PREV:
- mTransportControls.skipToPrevious();
- break;
- default:
- LogHelper.w(TAG, "Unknown intent ignored. Action=", action);
- }
- }
-
- /**
- * Update the state based on a change on the session token. Called either when
- * we are running for the first time or when the media session owner has destroyed the session
- * (see {@link android.media.session.MediaController.Callback#onSessionDestroyed()})
- */
- private void updateSessionToken() {
- MediaSession.Token freshToken = mService.getSessionToken();
- if (mSessionToken == null || !mSessionToken.equals(freshToken)) {
- if (mController != null) {
- mController.unregisterCallback(mCb);
- }
- mSessionToken = freshToken;
- mController = new MediaController(mService, mSessionToken);
- mTransportControls = mController.getTransportControls();
- if (mStarted) {
- mController.registerCallback(mCb);
- }
- }
- }
-
- private PendingIntent createContentIntent() {
- Intent openUI = new Intent(mService, MediaBrowserService.class);
- openUI.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
- return PendingIntent.getActivity(
- mService, REQUEST_CODE, openUI, PendingIntent.FLAG_CANCEL_CURRENT);
- }
-
- private final MediaController.Callback mCb = new MediaController.Callback() {
- @Override
- public void onPlaybackStateChanged(PlaybackState state) {
- mPlaybackState = state;
- LogHelper.d(TAG, "Received new playback state", state);
- if (state != null
- && (state.getState() == PlaybackState.STATE_STOPPED
- || state.getState() == PlaybackState.STATE_NONE)) {
- stopNotification();
- } else {
- Notification notification = createNotification();
- if (notification != null) {
- mNotificationManager.notify(NOTIFICATION_ID, notification);
- }
- }
- }
-
- @Override
- public void onMetadataChanged(MediaMetadata metadata) {
- mMetadata = metadata;
- LogHelper.d(TAG, "Received new metadata ", metadata);
- Notification notification = createNotification();
- if (notification != null) {
- mNotificationManager.notify(NOTIFICATION_ID, notification);
- }
- }
-
- @Override
- public void onSessionDestroyed() {
- super.onSessionDestroyed();
- LogHelper.d(TAG, "Session was destroyed, resetting to the new session token");
- updateSessionToken();
- }
- };
-
- private Notification createNotification() {
- LogHelper.d(TAG, "updateNotificationMetadata. mMetadata=" + mMetadata);
- if (mMetadata == null || mPlaybackState == null) {
- return null;
- }
-
- Notification.Builder notificationBuilder = new Notification.Builder(mService);
- int playPauseButtonPosition = 0;
-
- // If skip to previous action is enabled
- if ((mPlaybackState.getActions() & PlaybackState.ACTION_SKIP_TO_PREVIOUS) != 0) {
- notificationBuilder.addAction(R.drawable.ic_skip_previous_white_24dp,
- mService.getString(R.string.skip_previous), mPreviousIntent);
-
- // If there is a "skip to previous" button, the play/pause button will
- // be the second one. We need to keep track of it, because the MediaStyle notification
- // requires to specify the index of the buttons (actions) that should be visible
- // when in compact view.
- playPauseButtonPosition = 1;
- }
-
- addPlayPauseAction(notificationBuilder);
-
- // If skip to next action is enabled
- if ((mPlaybackState.getActions() & PlaybackState.ACTION_SKIP_TO_NEXT) != 0) {
- notificationBuilder.addAction(R.drawable.ic_skip_next_white_24dp,
- mService.getString(R.string.skip_next), mNextIntent);
- }
-
- MediaDescription description = mMetadata.getDescription();
-
- String fetchArtUrl = null;
- Bitmap art = null;
- if (description.getIconUri() != null) {
- // This sample assumes the iconUri will be a valid URL formatted String, but
- // it can actually be any valid Android Uri formatted String.
- // async fetch the album art icon
- String artUrl = description.getIconUri().toString();
- art = AlbumArtCache.getInstance().getBigImage(artUrl);
- if (art == null) {
- fetchArtUrl = artUrl;
- // use a placeholder art while the remote art is being downloaded
- art = BitmapFactory.decodeResource(
- mService.getResources(), R.drawable.ic_default_art);
- }
- }
-
- notificationBuilder
- .setStyle(new Notification.MediaStyle()
- .setShowActionsInCompactView(
- playPauseButtonPosition) // show only play/pause in
- // compact view
- .setMediaSession(mSessionToken))
- .setColor(mNotificationColor)
- .setSmallIcon(R.drawable.ic_notification)
- .setVisibility(Notification.VISIBILITY_PUBLIC)
- .setUsesChronometer(true)
- .setContentIntent(createContentIntent())
- .setContentTitle(description.getTitle())
- .setContentText(description.getSubtitle())
- .setLargeIcon(art);
-
- setNotificationPlaybackState(notificationBuilder);
- if (fetchArtUrl != null) {
- fetchBitmapFromURLAsync(fetchArtUrl, notificationBuilder);
- }
-
- return notificationBuilder.build();
- }
-
- private void addPlayPauseAction(Notification.Builder builder) {
- LogHelper.d(TAG, "updatePlayPauseAction");
- String label;
- int icon;
- PendingIntent intent;
- if (mPlaybackState.getState() == PlaybackState.STATE_PLAYING) {
- label = mService.getString(R.string.play_pause);
- icon = R.drawable.ic_pause_white_24dp;
- intent = mPauseIntent;
- } else {
- label = mService.getString(R.string.play_item);
- icon = R.drawable.ic_play_arrow_white_24dp;
- intent = mPlayIntent;
- }
- builder.addAction(new Notification.Action(icon, label, intent));
- }
-
- private void setNotificationPlaybackState(Notification.Builder builder) {
- LogHelper.d(TAG, "updateNotificationPlaybackState. mPlaybackState=" + mPlaybackState);
- if (mPlaybackState == null || !mStarted) {
- LogHelper.d(TAG, "updateNotificationPlaybackState. cancelling notification!");
- mService.stopForeground(true);
- return;
- }
- if (mPlaybackState.getState() == PlaybackState.STATE_PLAYING
- && mPlaybackState.getPosition() >= 0) {
- LogHelper.d(TAG, "updateNotificationPlaybackState. updating playback position to ",
- (System.currentTimeMillis() - mPlaybackState.getPosition()) / 1000, " seconds");
- builder.setWhen(System.currentTimeMillis() - mPlaybackState.getPosition())
- .setShowWhen(true)
- .setUsesChronometer(true);
- } else {
- LogHelper.d(TAG, "updateNotificationPlaybackState. hiding playback position");
- builder.setWhen(0).setShowWhen(false).setUsesChronometer(false);
- }
-
- // Make sure that the notification can be dismissed by the user when we are not playing:
- builder.setOngoing(mPlaybackState.getState() == PlaybackState.STATE_PLAYING);
- }
-
- private void fetchBitmapFromURLAsync(
- final String bitmapUrl, final Notification.Builder builder) {
- AlbumArtCache.getInstance().fetch(bitmapUrl, new AlbumArtCache.FetchListener() {
- @Override
- public void onFetched(String artUrl, Bitmap bitmap, Bitmap icon) {
- if (mMetadata != null && mMetadata.getDescription() != null
- && artUrl.equals(mMetadata.getDescription().getIconUri().toString())) {
- // If the media is still the same, update the notification:
- LogHelper.d(TAG, "fetchBitmapFromURLAsync: set bitmap to ", artUrl);
- builder.setLargeIcon(bitmap);
- mNotificationManager.notify(NOTIFICATION_ID, builder.build());
- }
- }
- });
- }
-}
diff --git a/src/com/android/music/utils/MusicProvider.java b/src/com/android/music/utils/MusicProvider.java
deleted file mode 100644
index 77ea9c1..0000000
--- a/src/com/android/music/utils/MusicProvider.java
+++ /dev/null
@@ -1,491 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music.utils;
-
-import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
-
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.drawable.BitmapDrawable;
-import android.media.MediaActionSound;
-import android.media.MediaMetadata;
-import android.media.MediaMetadataRetriever;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.provider.MediaStore;
-import android.util.Log;
-import com.android.music.MediaPlaybackService;
-import com.android.music.MusicUtils;
-import com.android.music.R;
-
-import java.io.File;
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-/*
-A provider of music contents to the music application, it reads external storage for any music
-files, parse them and
-store them in this class for future use.
- */
-public class MusicProvider {
- private static final String TAG = "MusicProvider";
-
- // Public constants
- public static final String UNKOWN = "UNKNOWN";
- // Uri source of this track
- public static final String CUSTOM_METADATA_TRACK_SOURCE = "__SOURCE__";
- // Sort key for this tack
- public static final String CUSTOM_METADATA_SORT_KEY = "__SORT_KEY__";
-
- // Content select criteria
- private static final String MUSIC_SELECT_FILTER = MediaStore.Audio.Media.IS_MUSIC + " != 0";
- private static final String MUSIC_SORT_ORDER = MediaStore.Audio.Media.TITLE + " ASC";
-
- // Categorized caches for music track data:
- private Context mContext;
- // Album Name --> list of Metadata
- private ConcurrentMap<String, List<MediaMetadata>> mMusicListByAlbum;
- // Playlist Name --> list of Metadata
- private ConcurrentMap<String, List<MediaMetadata>> mMusicListByPlaylist;
- // Artist Name --> Map of (album name --> album metadata)
- private ConcurrentMap<String, Map<String, MediaMetadata>> mArtistAlbumDb;
- private List<MediaMetadata> mMusicList;
- private final ConcurrentMap<Long, Song> mMusicListById;
- private final ConcurrentMap<String, Song> mMusicListByMediaId;
-
- enum State { NON_INITIALIZED, INITIALIZING, INITIALIZED }
-
- private volatile State mCurrentState = State.NON_INITIALIZED;
-
- public MusicProvider(Context context) {
- mContext = context;
- mArtistAlbumDb = new ConcurrentHashMap<>();
- mMusicListByAlbum = new ConcurrentHashMap<>();
- mMusicListByPlaylist = new ConcurrentHashMap<>();
- mMusicListById = new ConcurrentHashMap<>();
- mMusicList = new ArrayList<>();
- mMusicListByMediaId = new ConcurrentHashMap<>();
- mMusicListByPlaylist.put(MediaIDHelper.MEDIA_ID_NOW_PLAYING, new ArrayList<>());
- }
-
- public boolean isInitialized() {
- return mCurrentState == State.INITIALIZED;
- }
-
- /**
- * Get an iterator over the list of artists
- *
- * @return list of artists
- */
- public Iterable<String> getArtists() {
- if (mCurrentState != State.INITIALIZED) {
- return Collections.emptyList();
- }
- return mArtistAlbumDb.keySet();
- }
-
- /**
- * Get an iterator over the list of albums
- *
- * @return list of albums
- */
- public Iterable<MediaMetadata> getAlbums() {
- if (mCurrentState != State.INITIALIZED) {
- return Collections.emptyList();
- }
- ArrayList<MediaMetadata> albumList = new ArrayList<>();
- for (Map<String, MediaMetadata> artist_albums : mArtistAlbumDb.values()) {
- albumList.addAll(artist_albums.values());
- }
- return albumList;
- }
-
- /**
- * Get an iterator over the list of playlists
- *
- * @return list of playlists
- */
- public Iterable<String> getPlaylists() {
- if (mCurrentState != State.INITIALIZED) {
- return Collections.emptyList();
- }
- return mMusicListByPlaylist.keySet();
- }
-
- public Iterable<MediaMetadata> getMusicList() {
- return mMusicList;
- }
-
- /**
- * Get albums of a certain artist
- *
- */
- public Iterable<MediaMetadata> getAlbumByArtist(String artist) {
- if (mCurrentState != State.INITIALIZED || !mArtistAlbumDb.containsKey(artist)) {
- return Collections.emptyList();
- }
- return mArtistAlbumDb.get(artist).values();
- }
-
- /**
- * Get music tracks of the given album
- *
- */
- public Iterable<MediaMetadata> getMusicsByAlbum(String album) {
- if (mCurrentState != State.INITIALIZED || !mMusicListByAlbum.containsKey(album)) {
- return Collections.emptyList();
- }
- return mMusicListByAlbum.get(album);
- }
-
- /**
- * Get music tracks of the given playlist
- *
- */
- public Iterable<MediaMetadata> getMusicsByPlaylist(String playlist) {
- if (mCurrentState != State.INITIALIZED || !mMusicListByPlaylist.containsKey(playlist)) {
- return Collections.emptyList();
- }
- return mMusicListByPlaylist.get(playlist);
- }
-
- /**
- * Return the MediaMetadata for the given musicID.
- *
- * @param musicId The unique, non-hierarchical music ID.
- */
- public Song getMusicById(long musicId) {
- return mMusicListById.containsKey(musicId) ? mMusicListById.get(musicId) : null;
- }
-
- /**
- * Return the MediaMetadata for the given musicID.
- *
- * @param musicId The unique, non-hierarchical music ID.
- */
- public Song getMusicByMediaId(String musicId) {
- return mMusicListByMediaId.containsKey(musicId) ? mMusicListByMediaId.get(musicId) : null;
- }
-
- /**
- * Very basic implementation of a search that filter music tracks which title containing
- * the given query.
- *
- */
- public Iterable<MediaMetadata> searchMusic(String titleQuery) {
- if (mCurrentState != State.INITIALIZED) {
- return Collections.emptyList();
- }
- ArrayList<MediaMetadata> result = new ArrayList<>();
- titleQuery = titleQuery.toLowerCase();
- for (Song song : mMusicListByMediaId.values()) {
- if (song.getMetadata()
- .getString(MediaMetadata.METADATA_KEY_TITLE)
- .toLowerCase()
- .contains(titleQuery)) {
- result.add(song.getMetadata());
- }
- }
- return result;
- }
-
- public interface MusicProviderCallback { void onMusicCatalogReady(boolean success); }
-
- /**
- * Get the list of music tracks from disk and caches the track information
- * for future reference, keying tracks by musicId and grouping by genre.
- */
- public void retrieveMediaAsync(final MusicProviderCallback callback) {
- Log.d(TAG, "retrieveMediaAsync called");
- if (mCurrentState == State.INITIALIZED) {
- // Nothing to do, execute callback immediately
- callback.onMusicCatalogReady(true);
- return;
- }
-
- // Asynchronously load the music catalog in a separate thread
- new AsyncTask<Void, Void, State>() {
- @Override
- protected State doInBackground(Void... params) {
- if (mCurrentState == State.INITIALIZED) {
- return mCurrentState;
- }
- mCurrentState = State.INITIALIZING;
- if (retrieveMedia()) {
- mCurrentState = State.INITIALIZED;
- } else {
- mCurrentState = State.NON_INITIALIZED;
- }
- return mCurrentState;
- }
-
- @Override
- protected void onPostExecute(State current) {
- if (callback != null) {
- callback.onMusicCatalogReady(current == State.INITIALIZED);
- }
- }
- }
- .execute();
- }
-
- public synchronized boolean retrieveAllPlayLists() {
- Cursor cursor = mContext.getContentResolver().query(
- MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI, null, null, null, null);
- if (cursor == null) {
- Log.e(TAG, "Failed to retreive playlist: cursor is null");
- return false;
- }
- if (!cursor.moveToFirst()) {
- Log.d(TAG, "Failed to move cursor to first row (no query result)");
- cursor.close();
- return true;
- }
- int idColumn = cursor.getColumnIndex(MediaStore.Audio.Playlists._ID);
- int nameColumn = cursor.getColumnIndex(MediaStore.Audio.Playlists.NAME);
- int pathColumn = cursor.getColumnIndex(MediaStore.Audio.Playlists.DATA);
- do {
- long thisId = cursor.getLong(idColumn);
- String thisPath = cursor.getString(pathColumn);
- String thisName = cursor.getString(nameColumn);
- Log.i(TAG, "PlayList ID: " + thisId + " Name: " + thisName);
- List<MediaMetadata> songList = retreivePlaylistMetadata(thisId, thisPath);
- LogHelper.i(TAG, "Found ", songList.size(), " items for playlist name: ", thisName);
- mMusicListByPlaylist.put(thisName, songList);
- } while (cursor.moveToNext());
- cursor.close();
- return true;
- }
-
- public synchronized List<MediaMetadata> retreivePlaylistMetadata(
- long playlistId, String playlistPath) {
- Cursor cursor = mContext.getContentResolver().query(Uri.parse(playlistPath), null,
- MediaStore.Audio.Playlists.Members.PLAYLIST_ID + " == " + playlistId, null, null);
- if (cursor == null) {
- Log.e(TAG, "Failed to retreive individual playlist: cursor is null");
- return null;
- }
- if (!cursor.moveToFirst()) {
- Log.d(TAG, "Failed to move cursor to first row (no query result for playlist)");
- cursor.close();
- return null;
- }
- List<Song> songList = new ArrayList<>();
- int idColumn = cursor.getColumnIndex(MediaStore.Audio.Playlists.Members._ID);
- int audioIdColumn = cursor.getColumnIndex(MediaStore.Audio.Playlists.Members.AUDIO_ID);
- int orderColumn = cursor.getColumnIndex(MediaStore.Audio.Playlists.Members.PLAY_ORDER);
- int audioPathColumn = cursor.getColumnIndex(MediaStore.Audio.Playlists.Members.DATA);
- int audioNameColumn = cursor.getColumnIndex(MediaStore.Audio.Playlists.Members.TITLE);
- do {
- long thisId = cursor.getLong(idColumn);
- long thisAudioId = cursor.getLong(audioIdColumn);
- long thisOrder = cursor.getLong(orderColumn);
- String thisAudioPath = cursor.getString(audioPathColumn);
- Log.i(TAG,
- "Playlist ID: " + playlistId + " Music ID: " + thisAudioId
- + " Name: " + audioNameColumn);
- if (!mMusicListById.containsKey(thisAudioId)) {
- LogHelper.d(TAG, "Music does not exist");
- continue;
- }
- Song song = mMusicListById.get(thisAudioId);
- song.setSortKey(thisOrder);
- songList.add(song);
- } while (cursor.moveToNext());
- cursor.close();
- songList.sort(new Comparator<Song>() {
- @Override
- public int compare(Song s1, Song s2) {
- long key1 = s1.getSortKey();
- long key2 = s2.getSortKey();
- if (key1 < key2) {
- return -1;
- } else if (key1 == key2) {
- return 0;
- } else {
- return 1;
- }
- }
- });
- List<MediaMetadata> metadataList = new ArrayList<>();
- for (Song song : songList) {
- metadataList.add(song.getMetadata());
- }
- return metadataList;
- }
-
- private synchronized boolean retrieveMedia() {
- if (mContext.checkSelfPermission(READ_EXTERNAL_STORAGE)
- != PackageManager.PERMISSION_GRANTED) {
- return false;
- }
-
- Cursor cursor =
- mContext.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
- null, MUSIC_SELECT_FILTER, null, MUSIC_SORT_ORDER);
- if (cursor == null) {
- Log.e(TAG, "Failed to retreive music: cursor is null");
- mCurrentState = State.NON_INITIALIZED;
- return false;
- }
- if (!cursor.moveToFirst()) {
- Log.d(TAG, "Failed to move cursor to first row (no query result)");
- cursor.close();
- return true;
- }
- int idColumn = cursor.getColumnIndex(MediaStore.Audio.Media._ID);
- int titleColumn = cursor.getColumnIndex(MediaStore.Audio.Media.TITLE);
- int pathColumn = cursor.getColumnIndex(MediaStore.Audio.Media.DATA);
- do {
- Log.i(TAG,
- "Music ID: " + cursor.getString(idColumn)
- + " Title: " + cursor.getString(titleColumn));
- long thisId = cursor.getLong(idColumn);
- String thisPath = cursor.getString(pathColumn);
- MediaMetadata metadata = retrievMediaMetadata(thisId, thisPath);
- Log.i(TAG, "MediaMetadata: " + metadata);
- if (metadata == null) {
- continue;
- }
- Song thisSong = new Song(thisId, metadata, null);
- // Construct per feature database
- mMusicList.add(metadata);
- mMusicListById.put(thisId, thisSong);
- mMusicListByMediaId.put(String.valueOf(thisId), thisSong);
- addMusicToAlbumList(metadata);
- addMusicToArtistList(metadata);
- } while (cursor.moveToNext());
- cursor.close();
- return true;
- }
-
- private synchronized MediaMetadata retrievMediaMetadata(long musicId, String musicPath) {
- LogHelper.d(TAG, "getting metadata for music: ", musicPath);
- MediaMetadataRetriever retriever = new MediaMetadataRetriever();
- Uri contentUri = ContentUris.withAppendedId(
- android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, musicId);
- if (!(new File(musicPath).exists())) {
- LogHelper.d(TAG, "Does not exist, deleting item");
- mContext.getContentResolver().delete(contentUri, null, null);
- return null;
- }
- retriever.setDataSource(mContext, contentUri);
- String title = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
- String album = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
- String artist = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
- String durationString =
- retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
- long duration = durationString != null ? Long.parseLong(durationString) : 0;
- MediaMetadata.Builder metadataBuilder =
- new MediaMetadata.Builder()
- .putString(MediaMetadata.METADATA_KEY_MEDIA_ID, String.valueOf(musicId))
- .putString(CUSTOM_METADATA_TRACK_SOURCE, musicPath)
- .putString(MediaMetadata.METADATA_KEY_TITLE, title != null ? title : UNKOWN)
- .putString(MediaMetadata.METADATA_KEY_ALBUM, album != null ? album : UNKOWN)
- .putString(
- MediaMetadata.METADATA_KEY_ARTIST, artist != null ? artist : UNKOWN)
- .putLong(MediaMetadata.METADATA_KEY_DURATION, duration);
- byte[] albumArtData = retriever.getEmbeddedPicture();
- Bitmap bitmap;
- if (albumArtData != null) {
- bitmap = BitmapFactory.decodeByteArray(albumArtData, 0, albumArtData.length);
- bitmap = MusicUtils.resizeBitmap(bitmap, getDefaultAlbumArt());
- metadataBuilder.putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, bitmap);
- }
- retriever.release();
- return metadataBuilder.build();
- }
-
- private Bitmap getDefaultAlbumArt() {
- BitmapFactory.Options opts = new BitmapFactory.Options();
- opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
- return BitmapFactory.decodeStream(
- mContext.getResources().openRawResource(R.drawable.albumart_mp_unknown), null,
- opts);
- }
-
- private void addMusicToAlbumList(MediaMetadata metadata) {
- String thisAlbum = metadata.getString(MediaMetadata.METADATA_KEY_ALBUM);
- if (thisAlbum == null) {
- thisAlbum = UNKOWN;
- }
- if (!mMusicListByAlbum.containsKey(thisAlbum)) {
- mMusicListByAlbum.put(thisAlbum, new ArrayList<>());
- }
- mMusicListByAlbum.get(thisAlbum).add(metadata);
- }
-
- private void addMusicToArtistList(MediaMetadata metadata) {
- String thisArtist = metadata.getString(MediaMetadata.METADATA_KEY_ARTIST);
- if (thisArtist == null) {
- thisArtist = UNKOWN;
- }
- String thisAlbum = metadata.getString(MediaMetadata.METADATA_KEY_ALBUM);
- if (thisAlbum == null) {
- thisAlbum = UNKOWN;
- }
- if (!mArtistAlbumDb.containsKey(thisArtist)) {
- mArtistAlbumDb.put(thisArtist, new ConcurrentHashMap<>());
- }
- Map<String, MediaMetadata> albumsMap = mArtistAlbumDb.get(thisArtist);
- MediaMetadata.Builder builder;
- long count = 0;
- Bitmap thisAlbumArt = metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
- if (albumsMap.containsKey(thisAlbum)) {
- MediaMetadata album_metadata = albumsMap.get(thisAlbum);
- count = album_metadata.getLong(MediaMetadata.METADATA_KEY_NUM_TRACKS);
- Bitmap nAlbumArt = album_metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
- builder = new MediaMetadata.Builder(album_metadata);
- if (nAlbumArt != null) {
- thisAlbumArt = null;
- }
- } else {
- builder = new MediaMetadata.Builder();
- builder.putString(MediaMetadata.METADATA_KEY_ALBUM, thisAlbum)
- .putString(MediaMetadata.METADATA_KEY_ARTIST, thisArtist);
- }
- if (thisAlbumArt != null) {
- builder.putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, thisAlbumArt);
- }
- builder.putLong(MediaMetadata.METADATA_KEY_NUM_TRACKS, count + 1);
- albumsMap.put(thisAlbum, builder.build());
- }
-
- public synchronized void updateMusic(String musicId, MediaMetadata metadata) {
- Song song = mMusicListByMediaId.get(musicId);
- if (song == null) {
- return;
- }
-
- String oldGenre = song.getMetadata().getString(MediaMetadata.METADATA_KEY_GENRE);
- String newGenre = metadata.getString(MediaMetadata.METADATA_KEY_GENRE);
-
- song.setMetadata(metadata);
-
- // if genre has changed, we need to rebuild the list by genre
- if (!oldGenre.equals(newGenre)) {
- // buildListsByGenre();
- }
- }
-}
diff --git a/src/com/android/music/utils/Playback.java b/src/com/android/music/utils/Playback.java
deleted file mode 100644
index 02114bd..0000000
--- a/src/com/android/music/utils/Playback.java
+++ /dev/null
@@ -1,486 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.music.utils;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.media.AudioManager;
-import android.media.MediaMetadata;
-import android.media.MediaPlayer;
-import android.media.session.PlaybackState;
-import android.net.wifi.WifiManager;
-import android.os.PowerManager;
-import android.text.TextUtils;
-import android.util.Log;
-import com.android.music.MediaPlaybackService;
-
-import java.io.IOException;
-
-import static android.media.MediaPlayer.OnCompletionListener;
-import static android.media.MediaPlayer.OnErrorListener;
-import static android.media.MediaPlayer.OnPreparedListener;
-import static android.media.MediaPlayer.OnSeekCompleteListener;
-import static android.media.session.MediaSession.QueueItem;
-
-/**
- * A class that implements local media playback using {@link android.media.MediaPlayer}
- */
-public class Playback implements AudioManager.OnAudioFocusChangeListener, OnCompletionListener,
- OnErrorListener, OnPreparedListener, OnSeekCompleteListener {
- private static final String TAG = "Playback";
-
- // The volume we set the media player to when we lose audio focus, but are
- // allowed to reduce the volume instead of stopping playback.
- public static final float VOLUME_DUCK = 0.2f;
- // The volume we set the media player when we have audio focus.
- public static final float VOLUME_NORMAL = 1.0f;
-
- // we don't have audio focus, and can't duck (play at a low volume)
- private static final int AUDIO_NO_FOCUS_NO_DUCK = 0;
- // we don't have focus, but can duck (play at a low volume)
- private static final int AUDIO_NO_FOCUS_CAN_DUCK = 1;
- // we have full audio focus
- private static final int AUDIO_FOCUSED = 2;
-
- private final MediaPlaybackService mService;
- private final WifiManager.WifiLock mWifiLock;
- private int mState;
- private boolean mPlayOnFocusGain;
- private Callback mCallback;
- private MusicProvider mMusicProvider;
- private volatile boolean mAudioNoisyReceiverRegistered;
- private volatile int mCurrentPosition;
- private volatile String mCurrentMediaId;
-
- // Type of audio focus we have:
- private int mAudioFocus = AUDIO_NO_FOCUS_NO_DUCK;
- private AudioManager mAudioManager;
- private MediaPlayer mMediaPlayer;
-
- private IntentFilter mAudioNoisyIntentFilter =
- new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
-
- private BroadcastReceiver mAudioNoisyReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) {
- Log.d(TAG, "Headphones disconnected.");
- if (isPlaying()) {
- Intent i = new Intent(context, MediaPlaybackService.class);
- i.setAction(MediaPlaybackService.ACTION_CMD);
- i.putExtra(MediaPlaybackService.CMD_NAME, MediaPlaybackService.CMD_PAUSE);
- mService.startService(i);
- }
- }
- }
- };
-
- public Playback(MediaPlaybackService service, MusicProvider musicProvider) {
- this.mService = service;
- this.mMusicProvider = musicProvider;
- this.mAudioManager = (AudioManager) service.getSystemService(Context.AUDIO_SERVICE);
- // Create the Wifi lock (this does not acquire the lock, this just creates it)
- this.mWifiLock = ((WifiManager) service.getSystemService(Context.WIFI_SERVICE))
- .createWifiLock(WifiManager.WIFI_MODE_FULL, "sample_lock");
- }
-
- public void start() {}
-
- public void stop(boolean notifyListeners) {
- mState = PlaybackState.STATE_STOPPED;
- if (notifyListeners && mCallback != null) {
- mCallback.onPlaybackStatusChanged(mState);
- }
- mCurrentPosition = getCurrentStreamPosition();
- // Give up Audio focus
- giveUpAudioFocus();
- unregisterAudioNoisyReceiver();
- // Relax all resources
- relaxResources(true);
- if (mWifiLock.isHeld()) {
- mWifiLock.release();
- }
- }
-
- public void setState(int state) {
- this.mState = state;
- }
-
- public int getState() {
- return mState;
- }
-
- public boolean isConnected() {
- return true;
- }
-
- public boolean isPlaying() {
- return mPlayOnFocusGain || (mMediaPlayer != null && mMediaPlayer.isPlaying());
- }
-
- public int getCurrentStreamPosition() {
- return mMediaPlayer != null ? mMediaPlayer.getCurrentPosition() : mCurrentPosition;
- }
-
- public void play(QueueItem item) {
- mPlayOnFocusGain = true;
- tryToGetAudioFocus();
- registerAudioNoisyReceiver();
- String mediaId = item.getDescription().getMediaId();
- boolean mediaHasChanged = !TextUtils.equals(mediaId, mCurrentMediaId);
- if (mediaHasChanged) {
- mCurrentPosition = 0;
- mCurrentMediaId = mediaId;
- }
-
- if (mState == PlaybackState.STATE_PAUSED && !mediaHasChanged && mMediaPlayer != null) {
- configMediaPlayerState();
- } else {
- mState = PlaybackState.STATE_STOPPED;
- relaxResources(false); // release everything except MediaPlayer
- MediaMetadata track =
- mMusicProvider
- .getMusicByMediaId(MediaIDHelper.extractMusicIDFromMediaID(
- item.getDescription().getMediaId()))
- .getMetadata();
-
- String source = track.getString(MusicProvider.CUSTOM_METADATA_TRACK_SOURCE);
-
- try {
- createMediaPlayerIfNeeded();
-
- mState = PlaybackState.STATE_BUFFERING;
-
- mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
- mMediaPlayer.setDataSource(source);
-
- // Starts preparing the media player in the background. When
- // it's done, it will call our OnPreparedListener (that is,
- // the onPrepared() method on this class, since we set the
- // listener to 'this'). Until the media player is prepared,
- // we *cannot* call start() on it!
- mMediaPlayer.prepareAsync();
-
- // If we are streaming from the internet, we want to hold a
- // Wifi lock, which prevents the Wifi radio from going to
- // sleep while the song is playing.
- // mWifiLock.acquire();
-
- if (mCallback != null) {
- mCallback.onPlaybackStatusChanged(mState);
- }
-
- } catch (IOException ex) {
- Log.e(TAG, ex + "Exception playing song");
- if (mCallback != null) {
- mCallback.onError(ex.getMessage());
- }
- }
- }
- }
-
- public void pause() {
- if (mState == PlaybackState.STATE_PLAYING) {
- // Pause media player and cancel the 'foreground service' state.
- if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
- mMediaPlayer.pause();
- mCurrentPosition = mMediaPlayer.getCurrentPosition();
- }
- // while paused, retain the MediaPlayer but give up audio focus
- relaxResources(false);
- giveUpAudioFocus();
- }
- mState = PlaybackState.STATE_PAUSED;
- if (mCallback != null) {
- mCallback.onPlaybackStatusChanged(mState);
- }
- unregisterAudioNoisyReceiver();
- }
-
- public void seekTo(int position) {
- Log.d(TAG, "seekTo called with " + position);
-
- if (mMediaPlayer == null) {
- // If we do not have a current media player, simply update the current position
- mCurrentPosition = position;
- } else {
- if (mMediaPlayer.isPlaying()) {
- mState = PlaybackState.STATE_BUFFERING;
- }
- mMediaPlayer.seekTo(position);
- if (mCallback != null) {
- mCallback.onPlaybackStatusChanged(mState);
- }
- }
- }
-
- public void setCallback(Callback callback) {
- this.mCallback = callback;
- }
-
- /**
- * Try to get the system audio focus.
- */
- private void tryToGetAudioFocus() {
- Log.d(TAG, "tryToGetAudioFocus");
- if (mAudioFocus != AUDIO_FOCUSED) {
- int result = mAudioManager.requestAudioFocus(
- this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
- if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
- mAudioFocus = AUDIO_FOCUSED;
- }
- }
- }
-
- /**
- * Give up the audio focus.
- */
- private void giveUpAudioFocus() {
- Log.d(TAG, "giveUpAudioFocus");
- if (mAudioFocus == AUDIO_FOCUSED) {
- if (mAudioManager.abandonAudioFocus(this) == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
- mAudioFocus = AUDIO_NO_FOCUS_NO_DUCK;
- }
- }
- }
-
- /**
- * Reconfigures MediaPlayer according to audio focus settings and
- * starts/restarts it. This method starts/restarts the MediaPlayer
- * respecting the current audio focus state. So if we have focus, it will
- * play normally; if we don't have focus, it will either leave the
- * MediaPlayer paused or set it to a low volume, depending on what is
- * allowed by the current focus settings. This method assumes mPlayer !=
- * null, so if you are calling it, you have to do so from a context where
- * you are sure this is the case.
- */
- private void configMediaPlayerState() {
- Log.d(TAG, "configMediaPlayerState. mAudioFocus=" + mAudioFocus);
- if (mAudioFocus == AUDIO_NO_FOCUS_NO_DUCK) {
- // If we don't have audio focus and can't duck, we have to pause,
- if (mState == PlaybackState.STATE_PLAYING) {
- pause();
- }
- } else { // we have audio focus:
- if (mAudioFocus == AUDIO_NO_FOCUS_CAN_DUCK) {
- mMediaPlayer.setVolume(VOLUME_DUCK, VOLUME_DUCK); // we'll be relatively quiet
- } else {
- if (mMediaPlayer != null) {
- mMediaPlayer.setVolume(VOLUME_NORMAL, VOLUME_NORMAL); // we can be loud again
- } // else do something for remote client.
- }
- // If we were playing when we lost focus, we need to resume playing.
- if (mPlayOnFocusGain) {
- if (mMediaPlayer != null && !mMediaPlayer.isPlaying()) {
- Log.d(TAG,
- "configMediaPlayerState startMediaPlayer. seeking to "
- + mCurrentPosition);
- if (mCurrentPosition == mMediaPlayer.getCurrentPosition()) {
- mMediaPlayer.start();
- mState = PlaybackState.STATE_PLAYING;
- } else {
- mMediaPlayer.seekTo(mCurrentPosition);
- mState = PlaybackState.STATE_BUFFERING;
- }
- }
- mPlayOnFocusGain = false;
- }
- }
- if (mCallback != null) {
- mCallback.onPlaybackStatusChanged(mState);
- }
- }
-
- /**
- * Called by AudioManager on audio focus changes.
- * Implementation of {@link android.media.AudioManager.OnAudioFocusChangeListener}
- */
- @Override
- public void onAudioFocusChange(int focusChange) {
- Log.d(TAG, "onAudioFocusChange. focusChange=" + focusChange);
- if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
- // We have gained focus:
- mAudioFocus = AUDIO_FOCUSED;
-
- } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS
- || focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT
- || focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
- // We have lost focus. If we can duck (low playback volume), we can keep playing.
- // Otherwise, we need to pause the playback.
- boolean canDuck = focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK;
- mAudioFocus = canDuck ? AUDIO_NO_FOCUS_CAN_DUCK : AUDIO_NO_FOCUS_NO_DUCK;
-
- // If we are playing, we need to reset media player by calling configMediaPlayerState
- // with mAudioFocus properly set.
- if (mState == PlaybackState.STATE_PLAYING && !canDuck) {
- // If we don't have audio focus and can't duck, we save the information that
- // we were playing, so that we can resume playback once we get the focus back.
- mPlayOnFocusGain = true;
- }
- } else {
- Log.e(TAG, "onAudioFocusChange: Ignoring unsupported focusChange: " + focusChange);
- }
- configMediaPlayerState();
- }
-
- /**
- * Called when MediaPlayer has completed a seek
- *
- * @see android.media.MediaPlayer.OnSeekCompleteListener
- */
- @Override
- public void onSeekComplete(MediaPlayer mp) {
- Log.d(TAG, "onSeekComplete from MediaPlayer:" + mp.getCurrentPosition());
- mCurrentPosition = mp.getCurrentPosition();
- if (mState == PlaybackState.STATE_BUFFERING) {
- mMediaPlayer.start();
- mState = PlaybackState.STATE_PLAYING;
- }
- if (mCallback != null) {
- mCallback.onPlaybackStatusChanged(mState);
- }
- }
-
- /**
- * Called when media player is done playing current song.
- *
- * @see android.media.MediaPlayer.OnCompletionListener
- */
- @Override
- public void onCompletion(MediaPlayer player) {
- Log.d(TAG, "onCompletion from MediaPlayer");
- // The media player finished playing the current song, so we go ahead
- // and start the next.
- if (mCallback != null) {
- mCallback.onCompletion();
- }
- }
-
- /**
- * Called when media player is done preparing.
- *
- * @see android.media.MediaPlayer.OnPreparedListener
- */
- @Override
- public void onPrepared(MediaPlayer player) {
- Log.d(TAG, "onPrepared from MediaPlayer");
- // The media player is done preparing. That means we can start playing if we
- // have audio focus.
- configMediaPlayerState();
- }
-
- /**
- * Called when there's an error playing media. When this happens, the media
- * player goes to the Error state. We warn the user about the error and
- * reset the media player.
- *
- * @see android.media.MediaPlayer.OnErrorListener
- */
- @Override
- public boolean onError(MediaPlayer mp, int what, int extra) {
- Log.e(TAG, "Media player error: what=" + what + ", extra=" + extra);
- if (mCallback != null) {
- mCallback.onError("MediaPlayer error " + what + " (" + extra + ")");
- }
- return true; // true indicates we handled the error
- }
-
- /**
- * Makes sure the media player exists and has been reset. This will create
- * the media player if needed, or reset the existing media player if one
- * already exists.
- */
- private void createMediaPlayerIfNeeded() {
- Log.d(TAG, "createMediaPlayerIfNeeded. needed? " + (mMediaPlayer == null));
- if (mMediaPlayer == null) {
- mMediaPlayer = new MediaPlayer();
-
- // Make sure the media player will acquire a wake-lock while
- // playing. If we don't do that, the CPU might go to sleep while the
- // song is playing, causing playback to stop.
- mMediaPlayer.setWakeMode(
- mService.getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
-
- // we want the media player to notify us when it's ready preparing,
- // and when it's done playing:
- mMediaPlayer.setOnPreparedListener(this);
- mMediaPlayer.setOnCompletionListener(this);
- mMediaPlayer.setOnErrorListener(this);
- mMediaPlayer.setOnSeekCompleteListener(this);
- } else {
- mMediaPlayer.reset();
- }
- }
-
- /**
- * Releases resources used by the service for playback. This includes the
- * "foreground service" status, the wake locks and possibly the MediaPlayer.
- *
- * @param releaseMediaPlayer Indicates whether the Media Player should also
- * be released or not
- */
- private void relaxResources(boolean releaseMediaPlayer) {
- Log.d(TAG, "relaxResources. releaseMediaPlayer=" + releaseMediaPlayer);
-
- mService.stopForeground(true);
-
- // stop and release the Media Player, if it's available
- if (releaseMediaPlayer && mMediaPlayer != null) {
- mMediaPlayer.reset();
- mMediaPlayer.release();
- mMediaPlayer = null;
- }
-
- // we can also release the Wifi lock, if we're holding it
- if (mWifiLock.isHeld()) {
- mWifiLock.release();
- }
- }
-
- private void registerAudioNoisyReceiver() {
- if (!mAudioNoisyReceiverRegistered) {
- mService.registerReceiver(mAudioNoisyReceiver, mAudioNoisyIntentFilter);
- mAudioNoisyReceiverRegistered = true;
- }
- }
-
- private void unregisterAudioNoisyReceiver() {
- if (mAudioNoisyReceiverRegistered) {
- mService.unregisterReceiver(mAudioNoisyReceiver);
- mAudioNoisyReceiverRegistered = false;
- }
- }
-
- public interface Callback {
- /**
- * On current music completed.
- */
- void onCompletion();
- /**
- * on Playback status changed
- * Implementations can use this callback to update
- * playback state on the media sessions.
- */
- void onPlaybackStatusChanged(int state);
-
- /**
- * @param error to be added to the PlaybackState
- */
- void onError(String error);
- }
-}
diff --git a/src/com/android/music/utils/QueueHelper.java b/src/com/android/music/utils/QueueHelper.java
deleted file mode 100644
index 7e3c2fd..0000000
--- a/src/com/android/music/utils/QueueHelper.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music.utils;
-
-import android.media.MediaDescription;
-import android.media.MediaMetadata;
-import android.media.session.MediaSession;
-import android.os.Bundle;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-
-import static com.android.music.utils.MediaIDHelper.MEDIA_ID_MUSICS_BY_ARTIST;
-import static com.android.music.utils.MediaIDHelper.MEDIA_ID_MUSICS_BY_SEARCH;
-import static com.android.music.utils.MediaIDHelper.MEDIA_ID_MUSICS_BY_SONG;
-import static com.android.music.utils.MediaIDHelper.MEDIA_ID_MUSICS_BY_PLAYLIST;
-import static com.android.music.utils.MediaIDHelper.MEDIA_ID_MUSICS_BY_ALBUM;
-
-/**
- * Utility class to help on queue related tasks.
- */
-public class QueueHelper {
- private static final String TAG = LogHelper.makeLogTag(QueueHelper.class);
-
- public static List<MediaSession.QueueItem> getPlayingQueue(
- String mediaId, MusicProvider musicProvider) {
- // extract the browsing hierarchy from the media ID:
- String[] hierarchy = MediaIDHelper.getHierarchy(mediaId);
-
- if (hierarchy.length != 2) {
- LogHelper.e(TAG, "Could not build a playing queue for this mediaId: ", mediaId);
- return null;
- }
-
- String categoryType = hierarchy[0];
- String categoryValue = hierarchy[1];
- LogHelper.d(TAG, "Creating playing queue for ", categoryType, ", ", categoryValue);
-
- Iterable<MediaMetadata> tracks = null;
- // This sample only supports genre and by_search category types.
- switch (categoryType) {
- case MEDIA_ID_MUSICS_BY_SONG:
- tracks = musicProvider.getMusicList();
- break;
- case MEDIA_ID_MUSICS_BY_ALBUM:
- tracks = musicProvider.getMusicsByAlbum(categoryValue);
- break;
- case MEDIA_ID_MUSICS_BY_ARTIST:
- LogHelper.d(TAG, "Not supported");
- break;
- default:
- break;
- }
-
- if (tracks == null) {
- LogHelper.e(
- TAG, "Unrecognized category type: ", categoryType, " for mediaId ", mediaId);
- return null;
- }
-
- return convertToQueue(tracks, hierarchy[0], hierarchy[1]);
- }
-
- public static List<MediaSession.QueueItem> getPlayingQueueFromSearch(
- String query, MusicProvider musicProvider) {
- LogHelper.d(TAG, "Creating playing queue for musics from search ", query);
-
- return convertToQueue(musicProvider.searchMusic(query), MEDIA_ID_MUSICS_BY_SEARCH, query);
- }
-
- public static int getMusicIndexOnQueue(Iterable<MediaSession.QueueItem> queue, String mediaId) {
- int index = 0;
- for (MediaSession.QueueItem item : queue) {
- if (mediaId.equals(item.getDescription().getMediaId())) {
- return index;
- }
- index++;
- }
- return -1;
- }
-
- public static int getMusicIndexOnQueue(Iterable<MediaSession.QueueItem> queue, long queueId) {
- int index = 0;
- for (MediaSession.QueueItem item : queue) {
- if (queueId == item.getQueueId()) {
- return index;
- }
- index++;
- }
- return -1;
- }
-
- private static List<MediaSession.QueueItem> convertToQueue(
- Iterable<MediaMetadata> tracks, String... categories) {
- List<MediaSession.QueueItem> queue = new ArrayList<>();
- int count = 0;
- for (MediaMetadata track : tracks) {
- // We create a hierarchy-aware mediaID, so we know what the queue is about by looking
- // at the QueueItem media IDs.
- String hierarchyAwareMediaID =
- MediaIDHelper.createMediaID(track.getDescription().getMediaId(), categories);
- long duration = track.getLong(MediaMetadata.METADATA_KEY_DURATION);
- MediaDescription.Builder descriptionBuilder = new MediaDescription.Builder();
- MediaDescription description = track.getDescription();
- Bundle extras = description.getExtras();
- if (extras == null) {
- extras = new Bundle();
- }
- extras.putLong(MediaMetadata.METADATA_KEY_DURATION, duration);
- descriptionBuilder.setExtras(extras)
- .setMediaId(hierarchyAwareMediaID)
- .setTitle(description.getTitle())
- .setSubtitle(track.getString(MediaMetadata.METADATA_KEY_ARTIST))
- .setIconBitmap(description.getIconBitmap())
- .setIconUri(description.getIconUri())
- .setMediaUri(description.getMediaUri())
- .setDescription(description.getDescription());
-
- // We don't expect queues to change after created, so we use the item index as the
- // queueId. Any other number unique in the queue would work.
- MediaSession.QueueItem item =
- new MediaSession.QueueItem(descriptionBuilder.build(), count++);
- queue.add(item);
- }
- return queue;
- }
-
- /**
- * Create a random queue. For simplicity sake, instead of a random queue, we create a
- * queue using the first genre.
- *
- * @param musicProvider the provider used for fetching music.
- * @return list containing {@link android.media.session.MediaSession.QueueItem}'s
- */
- public static List<MediaSession.QueueItem> getRandomQueue(MusicProvider musicProvider) {
- Iterator<String> genres = musicProvider.getArtists().iterator();
- if (!genres.hasNext()) {
- return Collections.emptyList();
- }
- String genre = genres.next();
- Iterable<MediaMetadata> tracks = musicProvider.getMusicsByAlbum(genre);
-
- return convertToQueue(tracks, MEDIA_ID_MUSICS_BY_ARTIST, genre);
- }
-
- public static boolean isIndexPlayable(int index, List<MediaSession.QueueItem> queue) {
- return (queue != null && index >= 0 && index < queue.size());
- }
-}
diff --git a/src/com/android/music/utils/ResourceHelper.java b/src/com/android/music/utils/ResourceHelper.java
deleted file mode 100644
index d7773ff..0000000
--- a/src/com/android/music/utils/ResourceHelper.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music.utils;
-
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-
-/**
- * Generic reusable methods to handle resources.
- */
-public class ResourceHelper {
- /**
- * Get a color value from a theme attribute.
- * @param context used for getting the color.
- * @param attribute theme attribute.
- * @param defaultColor default to use.
- * @return color value
- */
- public static int getThemeColor(Context context, int attribute, int defaultColor) {
- int themeColor = 0;
- String packageName = context.getPackageName();
- try {
- Context packageContext = context.createPackageContext(packageName, 0);
- ApplicationInfo applicationInfo =
- context.getPackageManager().getApplicationInfo(packageName, 0);
- packageContext.setTheme(applicationInfo.theme);
- Resources.Theme theme = packageContext.getTheme();
- TypedArray ta = theme.obtainStyledAttributes(new int[] {attribute});
- themeColor = ta.getColor(0, defaultColor);
- ta.recycle();
- } catch (PackageManager.NameNotFoundException e) {
- e.printStackTrace();
- }
- return themeColor;
- }
-}
diff --git a/src/com/android/music/utils/Song.java b/src/com/android/music/utils/Song.java
deleted file mode 100644
index 1260f03..0000000
--- a/src/com/android/music/utils/Song.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music.utils;
-
-import android.media.MediaMetadata;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-
-/**
- * Holder class that encapsulates a MediaMetadata and allows the actual metadata to be modified
- * without requiring to rebuild the collections the metadata is in.
- */
-public class Song implements Parcelable {
- private MediaMetadata mMetadata;
- private long mSongId;
- private long mSortKey;
-
- public Song(long songId, MediaMetadata metadata, Long sortKey) {
- mMetadata = metadata;
- mSongId = songId;
- if (sortKey != null) {
- mSortKey = sortKey;
- }
- }
-
- public long getSongId() {
- return mSongId;
- }
- public long getSortKey() {
- return mSortKey;
- }
- public void setSortKey(long sortKey) {
- mSortKey = sortKey;
- }
-
- public MediaMetadata getMetadata() {
- return mMetadata;
- }
- public void setMetadata(MediaMetadata metadata) {
- mMetadata = metadata;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || o.getClass() != Song.class) {
- return false;
- }
-
- Song that = (Song) o;
-
- return mSongId == that.getSongId();
- }
-
- @Override
- public int hashCode() {
- return Long.hashCode(mSongId);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeLong(mSortKey);
- out.writeLong(mSongId);
- out.writeParcelable(mMetadata, flags);
- }
-
- public static final Parcelable.Creator<Song> CREATOR = new Parcelable.Creator<Song>() {
- public Song createFromParcel(Parcel in) {
- MediaMetadata metadata = in.readParcelable(null);
- long songId = in.readLong();
- long sortKey = in.readLong();
- return new Song(songId, metadata, sortKey);
- }
-
- public Song[] newArray(int size) {
- return new Song[size];
- }
- };
-}
diff --git a/tests/Android.mk b/tests/Android.mk
deleted file mode 100644
index d94233c..0000000
--- a/tests/Android.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_STATIC_JAVA_LIBRARIES := junit android.test.legacy
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := MusicTests
-
-LOCAL_INSTRUMENTATION_FOR := Music
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
deleted file mode 100644
index 7c1f055..0000000
--- a/tests/AndroidManifest.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.music.tests">
-
- <application/>
-
- <instrumentation android:name="com.android.music.tests.MusicPlayerLaunchPerformance"
- android:targetPackage="com.google.android.music"
- android:label="Music Launch Performance">
- </instrumentation>
-
- <instrumentation android:name="com.android.music.tests.MusicPlayerFunctionalTestRunner"
- android:targetPackage="com.google.android.music"
- android:label="Music Player Functional Test">
- </instrumentation>
-
- <instrumentation android:name="com.android.music.tests.MusicPlayerStressTestRunner"
- android:targetPackage="com.google.android.music"
- android:label="Music Player Stress Test">
- </instrumentation>
-
-</manifest>
diff --git a/tests/src/com/android/music/MusicPlayerFunctionalTestRunner.java b/tests/src/com/android/music/MusicPlayerFunctionalTestRunner.java
deleted file mode 100644
index bacb7e2..0000000
--- a/tests/src/com/android/music/MusicPlayerFunctionalTestRunner.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music.tests;
-
-import android.test.InstrumentationTestRunner;
-import android.test.InstrumentationTestSuite;
-import com.android.music.tests.functional.TestSongs;
-import com.android.music.tests.functional.TestPlaylist;
-
-import junit.framework.TestSuite;
-
-
-/**
- * Instrumentation Test Runner for all Music Player tests.
- *
- * Precondition: Opened keyboard and wipe the userdata
- *
- * Running all tests:
- *
- * adb shell am instrument \
- * -w com.android.music.tests/.MusicPlayerFunctionalTestRunner
- */
-
-public class MusicPlayerFunctionalTestRunner extends InstrumentationTestRunner {
-
-
- @Override
- public TestSuite getAllTests() {
- TestSuite suite = new InstrumentationTestSuite(this);
- suite.addTestSuite(TestSongs.class);
- suite.addTestSuite(TestPlaylist.class);
- suite.addTestSuite(MusicPlayerStability.class);
- return suite;
- }
-
- @Override
- public ClassLoader getLoader() {
- return MusicPlayerFunctionalTestRunner.class.getClassLoader();
- }
-}
-
-
-
diff --git a/tests/src/com/android/music/MusicPlayerLaunchPerformance.java b/tests/src/com/android/music/MusicPlayerLaunchPerformance.java
deleted file mode 100644
index 80342ba..0000000
--- a/tests/src/com/android/music/MusicPlayerLaunchPerformance.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music.tests;
-
-import android.app.Activity;
-import android.test.LaunchPerformanceBase;
-import android.os.Bundle;
-
-import java.util.Map;
-
-/**
- * Instrumentation class for Media Player launch performance testing.
- */
-public class MusicPlayerLaunchPerformance extends LaunchPerformanceBase {
-
- public static final String LOG_TAG = "MusicPlayerLaunchPerformance";
-
- public MusicPlayerLaunchPerformance() {
- super();
- }
-
- @Override
- public void onCreate(Bundle arguments) {
- super.onCreate(arguments);
-
- mIntent.setClassName(getTargetContext(), "com.android.music.MusicBrowserActivity");
- start();
- }
-
- /**
- * Calls LaunchApp and finish.
- */
- @Override
- public void onStart() {
- super.onStart();
- LaunchApp();
- finish(Activity.RESULT_OK, mResults);
- }
-}
diff --git a/tests/src/com/android/music/MusicPlayerNames.java b/tests/src/com/android/music/MusicPlayerNames.java
deleted file mode 100644
index 655d578..0000000
--- a/tests/src/com/android/music/MusicPlayerNames.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music.tests;
-
-import android.os.Environment;
-
-/**
- *
- * This class has the names of the all the activity name and variables
- * in the instrumentation test.
- *
- */
-public class MusicPlayerNames {
-
- //Expected result of the sorted playlistname
- public static final String expectedPlaylistTitle[] = { "**1E?:|}{[]~~.,;'",
- "//><..", "0123456789",
- "0random@112", "MyPlaylist", "UPPERLETTER",
- "combination011", "loooooooog",
- "normal", "~!@#$%^&*()_+"
- };
-
- //Unsorted input playlist name
- public static final String unsortedPlaylistTitle[] = { "//><..","MyPlaylist",
- "0random@112", "UPPERLETTER","normal",
- "combination011", "0123456789",
- "~!@#$%^&*()_+","**1E?:|}{[]~~.,;'",
- "loooooooog"
- };
-
- public static final String DELETE_PLAYLIST_NAME = "testDeletPlaylist";
- public static final String ORIGINAL_PLAYLIST_NAME = "original_playlist_name";
- public static final String RENAMED_PLAYLIST_NAME = "rename_playlist_name";
-
- public static int NO_OF_PLAYLIST = 10;
- public static int WAIT_SHORT_TIME = 1000;
- public static int WAIT_LONG_TIME = 2000;
- public static int WAIT_VERY_LONG_TIME = 6000;
- public static int SKIP_WAIT_TIME = 500;
- public static int DEFAULT_PLAYLIST_LENGTH = 15;
- public static int NO_ALBUMS_TOBE_PLAYED = 50;
- public static int NO_SKIPPING_SONGS = 500;
-
- public static final String EXTERNAL_DIR =
- Environment.getExternalStorageDirectory().toString();
- public static final String DELETESONG = EXTERNAL_DIR + "/toBeDeleted.amr";
- public static final String GOLDENSONG = EXTERNAL_DIR + "/media_api/music/AMRNB.amr";
- public static final String TOBEDELETESONGNAME = "toBeDeleted";
-
- public static int EXPECTED_NO_RINGTONE = 1;
-}
diff --git a/tests/src/com/android/music/MusicPlayerStability.java b/tests/src/com/android/music/MusicPlayerStability.java
deleted file mode 100644
index d84d2f8..0000000
--- a/tests/src/com/android/music/MusicPlayerStability.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music.tests;
-
-import android.app.Instrumentation;
-import com.android.music.TrackBrowserActivity;
-import android.view.KeyEvent;
-import android.widget.ListView;
-
-import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.LargeTest;
-
-/**
- * Junit / Instrumentation test case for the Music Player
- */
-
-public class MusicPlayerStability extends ActivityInstrumentationTestCase2 <TrackBrowserActivity>{
- private static String TAG = "musicplayerstability";
- private static int PLAY_TIME = 30000;
- private ListView mTrackList;
-
- public MusicPlayerStability() {
- super("com.android.music",TrackBrowserActivity.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- getActivity();
- super.setUp();
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- }
-
- /**
- * Test case 1: This test case is for the power and general stability
- * measurment. We don't need to do the validation. This test case simply
- * play the mp3 for 30 seconds then stop.
- * The sdcard should have the target mp3 files.
- */
- @LargeTest
- public void testPlay30sMP3() throws Exception {
- // Launch the songs list. Pick the fisrt song and play
- try {
- Instrumentation inst = getInstrumentation();
- //Make sure the song list shown up
- Thread.sleep(2000);
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
- mTrackList = getActivity().getListView();
- int scrollCount = mTrackList.getMaxScrollAmount();
- //Make sure there is at least one song in the sdcard
- if (scrollCount != -1) {
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
- } else {
- assertTrue("testPlayMP3", false);
- }
- Thread.sleep(PLAY_TIME);
- } catch (Exception e) {
- assertTrue("testPlayMP3", false);
- }
- }
-
- @LargeTest
- public void testLaunchMusicPlayer() throws Exception {
- // Launch music player and sleep for 30 seconds to capture
- // the music player power usage base line.
- try {
- Thread.sleep(PLAY_TIME);
- } catch (Exception e) {
- assertTrue("MusicPlayer Do Nothing", false);
- }
- assertTrue("MusicPlayer Do Nothing", true);
- }
-}
diff --git a/tests/src/com/android/music/MusicPlayerStressTestRunner.java b/tests/src/com/android/music/MusicPlayerStressTestRunner.java
deleted file mode 100644
index 269627d..0000000
--- a/tests/src/com/android/music/MusicPlayerStressTestRunner.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.music.tests;
-
-import com.android.music.tests.stress.AlbumsPlaybackStress;
-import com.android.music.tests.stress.MusicPlaybackStress;
-
-import android.test.InstrumentationTestRunner;
-import android.test.InstrumentationTestSuite;
-
-import junit.framework.TestSuite;
-
-/**
- * Instrumentation Test Runner for all music player stress tests.
- *
- * Running all tests:
- *
- * adb shell am instrument \
- * -w com.android.music.tests/.MusicPlayerStressTestRunner
- */
-
-public class MusicPlayerStressTestRunner extends InstrumentationTestRunner {
-
- @Override
- public TestSuite getAllTests() {
- TestSuite suite = new InstrumentationTestSuite(this);
- //suite.addTestSuite(MusicPlaybackStress.class);
- suite.addTestSuite(AlbumsPlaybackStress.class);
- return suite;
- }
-
- @Override
- public ClassLoader getLoader() {
- return MusicPlayerStressTestRunner.class.getClassLoader();
- }
-}
-
diff --git a/tests/src/com/android/music/functional/TestPlaylist.java b/tests/src/com/android/music/functional/TestPlaylist.java
deleted file mode 100644
index e751eb1..0000000
--- a/tests/src/com/android/music/functional/TestPlaylist.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music.tests.functional;
-
-import android.app.Activity;
-import android.content.*;
-import android.app.Instrumentation;
-import android.app.Instrumentation.ActivityMonitor;
-import android.content.Intent;
-import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.view.KeyEvent;
-import android.provider.MediaStore;
-import android.content.ContentResolver;
-import android.database.Cursor;
-
-import com.android.music.MusicUtils;
-import com.android.music.PlaylistBrowserActivity;
-import com.android.music.TrackBrowserActivity;
-
-import com.android.music.tests.MusicPlayerNames;
-import com.android.music.tests.functional.TestSongs;
-
-/**
- * Junit / Instrumentation test case for the PlaylistBrowserActivity
- * This test case need to run in the landscape mode and opened keyboard
- */
-public class TestPlaylist extends ActivityInstrumentationTestCase<PlaylistBrowserActivity> {
- private static String TAG = "musicplayertests";
-
- public TestPlaylist() {
- super("com.android.music", PlaylistBrowserActivity.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- }
-
- private void clearSearchString(int length) {
- Instrumentation inst = getInstrumentation();
- for (int j = 0; j < length; j++) {
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DEL);
- }
- }
-
- /**
- * Remove playlist
- */
- public void deletePlaylist(String playlistname) throws Exception {
- Instrumentation inst = getInstrumentation();
- inst.sendStringSync(playlistname);
- Thread.sleep(MusicPlayerNames.WAIT_SHORT_TIME);
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
- inst.invokeContextMenuAction(getActivity(), 0 + 1, 0);
- Thread.sleep(MusicPlayerNames.WAIT_SHORT_TIME);
- clearSearchString(playlistname.length());
- }
-
- /**
- * Start the trackBrowserActivity and add the new playlist
- */
- public void addNewPlaylist(String playListName) throws Exception {
- Instrumentation inst = getInstrumentation();
- Activity trackBrowserActivity;
- ActivityMonitor trackBrowserMon =
- inst.addMonitor("com.android.music.TrackBrowserActivity", null, false);
- Intent intent = new Intent();
- intent.setAction(Intent.ACTION_PICK);
- intent.setClassName("com.android.music", "com.android.music.TrackBrowserActivity");
- getActivity().startActivity(intent);
- Thread.sleep(MusicPlayerNames.WAIT_LONG_TIME);
- trackBrowserActivity = trackBrowserMon.waitForActivityWithTimeout(2000);
- inst.invokeContextMenuAction(trackBrowserActivity, 0, 0);
- Thread.sleep(MusicPlayerNames.WAIT_SHORT_TIME);
- //Remove the default playlist name
- clearSearchString(MusicPlayerNames.DEFAULT_PLAYLIST_LENGTH);
- inst.sendStringSync(playListName);
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
- Thread.sleep(MusicPlayerNames.WAIT_LONG_TIME);
- trackBrowserActivity.finish();
- clearSearchString(playListName.length());
-
- }
-
- /**
- * Rename playlist
- */
- public void renamePlaylist(String oldPlaylistName, String newPlaylistName) throws Exception {
- Instrumentation inst = getInstrumentation();
- inst.sendStringSync(oldPlaylistName);
- Thread.sleep(MusicPlayerNames.WAIT_SHORT_TIME);
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
- inst.invokeContextMenuAction(getActivity(), 0 + 3, 0);
- Thread.sleep(MusicPlayerNames.WAIT_SHORT_TIME);
- //Remove the old playlist name
- clearSearchString(oldPlaylistName.length());
- inst.sendStringSync(newPlaylistName);
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
- Thread.sleep(MusicPlayerNames.WAIT_LONG_TIME);
- clearSearchString(oldPlaylistName.length());
- }
-
- public boolean verifyPlaylist(String playlistname) throws Exception {
- Cursor mCursor;
- boolean isEmptyPlaylist = true;
- String[] cols = new String[] {MediaStore.Audio.Playlists.NAME};
- ContentResolver resolver = getActivity().getContentResolver();
- if (resolver == null) {
- System.out.println("resolver = null");
- assertNull(TAG, resolver);
- } else {
- String whereclause = MediaStore.Audio.Playlists.NAME + " = '" + playlistname + "'";
- mCursor = resolver.query(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
- cols, whereclause, null,
- MediaStore.Audio.Playlists.NAME);
- isEmptyPlaylist = mCursor.moveToFirst();
- }
- return isEmptyPlaylist;
- }
-
- /**
- * Test case 1: Add a playlist and delet the playlist just added.
- * Verification: The mediastore playlist should be empty
- */
- @LargeTest
- public void testDeletePlaylist() throws Exception {
- boolean isEmptyPlaylist = true;
- addNewPlaylist(MusicPlayerNames.DELETE_PLAYLIST_NAME);
- deletePlaylist(MusicPlayerNames.DELETE_PLAYLIST_NAME);
- isEmptyPlaylist = verifyPlaylist(MusicPlayerNames.DELETE_PLAYLIST_NAME);
- assertFalse("testDeletePlaylist", isEmptyPlaylist);
- }
-
- /**
- * Test case 2: Add playlist and rename the playlist just added.
- * Verification: The mediastore playlist should contain the updated name.
- */
- @LargeTest
- public void testRenamePlaylist() throws Exception {
- boolean isEmptyPlaylist = true;
- addNewPlaylist(MusicPlayerNames.ORIGINAL_PLAYLIST_NAME);
- renamePlaylist(
- MusicPlayerNames.ORIGINAL_PLAYLIST_NAME, MusicPlayerNames.RENAMED_PLAYLIST_NAME);
- isEmptyPlaylist = verifyPlaylist(MusicPlayerNames.RENAMED_PLAYLIST_NAME);
- deletePlaylist(MusicPlayerNames.RENAMED_PLAYLIST_NAME);
- assertTrue("testDeletePlaylist", isEmptyPlaylist);
- }
-}
diff --git a/tests/src/com/android/music/functional/TestSongs.java b/tests/src/com/android/music/functional/TestSongs.java
deleted file mode 100644
index 8bb2875..0000000
--- a/tests/src/com/android/music/functional/TestSongs.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.music.tests.functional;
-
-import android.app.Activity;
-import android.content.*;
-import android.app.Instrumentation;
-import android.content.Intent;
-import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.net.Uri;
-import android.os.Environment;
-import android.provider.MediaStore;
-import android.content.ContentResolver;
-import android.content.pm.ActivityInfo;
-import android.database.Cursor;
-import android.content.Intent;
-import android.content.BroadcastReceiver;
-import android.content.IntentFilter;
-
-import com.android.music.TrackBrowserActivity;
-import com.android.music.MusicUtils;
-
-import com.android.music.tests.MusicPlayerNames;
-
-import java.io.*;
-
-/**
- * Junit / Instrumentation test case for the TrackBrowserActivity
- */
-public class TestSongs extends ActivityInstrumentationTestCase<TrackBrowserActivity> {
- private static String TAG = "musicplayertests";
-
- public TestSongs() {
- super("com.android.music", TrackBrowserActivity.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- }
-
- /**
- * Add 10 new playlists with unsorted title order
- */
- public void addNewPlaylist() throws Exception {
- Instrumentation inst = getInstrumentation();
- for (int i = 0; i < MusicPlayerNames.NO_OF_PLAYLIST; i++) {
- inst.invokeContextMenuAction(getActivity(), 0, 0);
- Thread.sleep(MusicPlayerNames.WAIT_SHORT_TIME);
- // Remove the default playlist name
- for (int j = 0; j < MusicPlayerNames.DEFAULT_PLAYLIST_LENGTH; j++) {
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DEL);
- }
- inst.sendStringSync(MusicPlayerNames.unsortedPlaylistTitle[i]);
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
- Thread.sleep(MusicPlayerNames.WAIT_LONG_TIME);
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
- Thread.sleep(MusicPlayerNames.WAIT_LONG_TIME);
- }
- }
-
- private void copy(File src, File dst) throws IOException {
- InputStream in = new FileInputStream(src);
- OutputStream out = new FileOutputStream(dst);
-
- // Transfer bytes from in to out
- byte[] buf = new byte[1024];
- int len;
- while ((len = in.read(buf)) > 0) {
- out.write(buf, 0, len);
- }
- in.close();
- out.close();
- Log.v(TAG, "Copy file");
- }
-
- // Rescan the sdcard after copy the file
- private void rescanSdcard() throws Exception {
- Intent scanIntent = new Intent(Intent.ACTION_MEDIA_MOUNTED,
- Uri.parse("file://" + Environment.getExternalStorageDirectory()));
- Log.v(TAG, "start the intent");
- IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_SCANNER_STARTED);
- intentFilter.addDataScheme("file");
- getActivity().sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
- Uri.parse("file://" + Environment.getExternalStorageDirectory())));
- Thread.sleep(MusicPlayerNames.WAIT_VERY_LONG_TIME);
- }
-
- /**
- * Test case 1: tests the new playlist added with sorted order.
- * Verification: The new playlist title should be sorted in alphabetical order
- */
- @LargeTest
- public void testAddPlaylist() throws Exception {
- Cursor mCursor;
- addNewPlaylist();
-
- // Verify the new playlist is created, check the playlist table
- String[] cols = new String[] {MediaStore.Audio.Playlists.NAME};
- ContentResolver resolver = getActivity().getContentResolver();
- if (resolver == null) {
- System.out.println("resolver = null");
- } else {
- String whereclause = MediaStore.Audio.Playlists.NAME + " != ''";
- mCursor = resolver.query(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI, cols,
- whereclause, null, MediaStore.Audio.Playlists.NAME);
- // Check the new playlist
- mCursor.moveToFirst();
-
- for (int j = 0; j < 10; j++) {
- assertEquals("New sorted Playlist title:",
- MusicPlayerNames.expectedPlaylistTitle[j], mCursor.getString(0));
- mCursor.moveToNext();
- }
- }
- }
-
- /**
- * Test case 2: Set a song as ringtone
- * Test case precondition: The testing device should wipe data before
- * run the test case.
- * Verification: The count of audio.media.is_ringtone equal to 1.
- */
- @LargeTest
- public void testSetRingtone() throws Exception {
- Cursor mCursor;
- Instrumentation inst = getInstrumentation();
- inst.invokeContextMenuAction(getActivity(), 0, 0);
- // This only check if there only 1 ringtone set in music player
- ContentResolver resolver = getActivity().getContentResolver();
- if (resolver == null) {
- System.out.println("resolver = null");
- } else {
- String whereclause = MediaStore.Audio.Media.IS_RINGTONE + " = 1";
- mCursor = resolver.query(
- MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, whereclause, null, null);
- // Check the new playlist
- mCursor.moveToFirst();
- int isRingtoneSet = mCursor.getCount();
- assertEquals(TAG, MusicPlayerNames.EXPECTED_NO_RINGTONE, isRingtoneSet);
- }
- }
-
- /**
- * Test case 3: Delete a song
- * Test case precondition: Copy a song and rescan the sdcard
- * Verification: The song is deleted from the sdcard and mediastore
- */
- @LargeTest
- public void testDeleteSong() throws Exception {
- Instrumentation inst = getInstrumentation();
- Cursor mCursor;
-
- // Copy a song from the golden directory
- Log.v(TAG, "Copy a temp file to the sdcard");
- File goldenfile = new File(MusicPlayerNames.GOLDENSONG);
- File toBeDeleteSong = new File(MusicPlayerNames.DELETESONG);
- copy(goldenfile, toBeDeleteSong);
- rescanSdcard();
-
- // Delete the file from music player
- Thread.sleep(MusicPlayerNames.WAIT_LONG_TIME);
- inst.sendStringSync(MusicPlayerNames.TOBEDELETESONGNAME);
- Thread.sleep(MusicPlayerNames.WAIT_LONG_TIME);
- inst.invokeContextMenuAction(getActivity(), 0, 0);
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
- Thread.sleep(MusicPlayerNames.WAIT_LONG_TIME);
-
- // Clear the search string
- for (int j = 0; j < MusicPlayerNames.TOBEDELETESONGNAME.length(); j++) {
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DEL);
- }
-
- // Verfiy the item is removed from sdcard
- File checkDeletedFile = new File(MusicPlayerNames.DELETESONG);
- assertFalse(TAG, checkDeletedFile.exists());
-
- ContentResolver resolver = getActivity().getContentResolver();
- if (resolver == null) {
- System.out.println("resolver = null");
- } else {
- String whereclause = MediaStore.Audio.Media.DISPLAY_NAME + " = '"
- + MusicPlayerNames.TOBEDELETESONGNAME + "'";
- mCursor = resolver.query(
- MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, whereclause, null, null);
- boolean isEmptyCursor = mCursor.moveToFirst();
- assertFalse(TAG, isEmptyCursor);
- }
- }
-}
diff --git a/tests/src/com/android/music/stress/AlbumsPlaybackStress.java b/tests/src/com/android/music/stress/AlbumsPlaybackStress.java
deleted file mode 100644
index 46e1d9f..0000000
--- a/tests/src/com/android/music/stress/AlbumsPlaybackStress.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.music.tests.stress;
-
-import android.app.Activity;
-import android.app.ActivityManager;
-import android.app.Instrumentation;
-import android.app.Instrumentation.ActivityMonitor;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.SystemClock;
-import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.view.KeyEvent;
-import android.util.Log;
-
-import com.android.music.AlbumBrowserActivity;
-import com.android.music.tests.MusicPlayerNames;
-
-public class AlbumsPlaybackStress extends ActivityInstrumentationTestCase <AlbumBrowserActivity>{
-
- private Activity browseActivity;
- private String[] testing;
- private String TAG = "AlbumsPlaybackStress";
-
- public AlbumsPlaybackStress() {
- super("com.android.music",AlbumBrowserActivity.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- }
-
- /*
- * Test case: Keeps launching music playback from Albums and then go
- * back to the album screen
- * Verification: Check if it is in low memory
- * The test depends on the test media in the sdcard
- */
- @LargeTest
- public void testAlbumPlay() {
- Instrumentation inst = getInstrumentation();
- try{
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_RIGHT);
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_RIGHT);
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
- Thread.sleep(MusicPlayerNames.WAIT_LONG_TIME);
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
- for(int i=0; i< MusicPlayerNames.NO_ALBUMS_TOBE_PLAYED; i++){
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
- Thread.sleep(MusicPlayerNames.WAIT_LONG_TIME);
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
- }
- }catch (Exception e){
- Log.v(TAG, e.toString());
- }
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
-
- //Verification: check if it is in low memory
- ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
- ((ActivityManager)getActivity().getSystemService(Context.ACTIVITY_SERVICE)).getMemoryInfo(mi);
- assertFalse(TAG, mi.lowMemory);
-
-
- }
-}
diff --git a/tests/src/com/android/music/stress/MusicPlaybackStress.java b/tests/src/com/android/music/stress/MusicPlaybackStress.java
deleted file mode 100644
index 10afd9d..0000000
--- a/tests/src/com/android/music/stress/MusicPlaybackStress.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.music.tests.stress;
-
-import android.app.Activity;
-import android.app.ActivityManager;
-import android.app.Instrumentation;
-import android.app.Instrumentation.ActivityMonitor;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.SystemClock;
-import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.view.KeyEvent;
-import android.util.Log;
-import android.content.Context;
-
-
-import com.android.music.MusicBrowserActivity;
-import com.android.music.MusicUtils;
-import com.android.music.TrackBrowserActivity;
-import com.android.music.tests.MusicPlayerNames;
-
-public class MusicPlaybackStress extends ActivityInstrumentationTestCase<TrackBrowserActivity> {
- private static String TAG = "mediaplayertests";
-
- public MusicPlaybackStress() {
- super("com.android.music", TrackBrowserActivity.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- }
-
- @LargeTest
- public void testPlayAllSongs() {
- Activity mediaPlaybackActivity;
- try {
- Instrumentation inst = getInstrumentation();
- ActivityMonitor mediaPlaybackMon =
- inst.addMonitor("com.android.music.MediaPlaybackActivity", null, false);
- inst.invokeMenuActionSync(getActivity(), 0 + 3, 0);
- Thread.sleep(MusicPlayerNames.WAIT_LONG_TIME);
- mediaPlaybackActivity = mediaPlaybackMon.waitForActivityWithTimeout(2000);
- for (int i = 0; i < MusicPlayerNames.NO_SKIPPING_SONGS; i++) {
- Thread.sleep(MusicPlayerNames.SKIP_WAIT_TIME);
- if (i == 0) {
- // Set the repeat all
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_RIGHT);
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_UP);
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
-
- // Set focus on the next button
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
- }
- inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
- }
- mediaPlaybackActivity.finish();
- } catch (Exception e) {
- Log.e(TAG, e.toString());
- }
- // Verification: check if it is in low memory
- ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
- ((ActivityManager) getActivity().getSystemService(Context.ACTIVITY_SERVICE))
- .getMemoryInfo(mi);
- assertFalse(TAG, mi.lowMemory);
- }
-}