Audio Player for Android OS

3 downloads 201952 Views 460KB Size Report
system (OS) for which it is developed is Android – an OS for mobile devices developed by ... purpose is to create an app with simplest interface possible for the user while not affecting its ..... a flag in the class, and the second one calls the.
CAx Technologies, issue 3, December 2015, ISSN 1314-9628

Audio Player for Android OS Vladimir Dimitrov Technical University of Sofia, Bulgaria E-mail: [email protected]

Kiril Aleksandrov Technical University of Sofia, Bulgaria E-mail: [email protected]

Abstract. The proposed application, subject to the present article is an audio player. The operating system (OS) for which it is developed is Android – an OS for mobile devices developed by Google. The programmable language used for its realization is Java that is the main language used for the development of applications for Android while the environment used for development is Eclipse. The purpose is to create an app with simplest interface possible for the user while not affecting its functionality. The OS used during the development is Fedora Linux but Microsoft Windows or Apple OSX could be used with the same effect as the tools for developing Android applications (apps) are platform independent. Keywords: Audio Player, Android, Java possibility to manipulate the music play. The screens are the following:

1. INTRODUCTION Audio Player is an application whose main function is to read audio files and to reproduce them as sound for the user. For sure this is its most basic functionality. Most players add any other additional functionalities to facilitate the user in his experience with the app and to give him the possibility to fully enjoy it. In order for it to be useful the app should not only implement the basic audio player functionalities, but it must also upgrade with others which could be interesting and useful for the end user. The functionalities chosen for the realization are the following:

      

Loading Screen Media Library Performers Albums Songs Details Player

The navigation between the different screens is shown in figure 1. The navigation in straight direction is achieved via interaction with some of the objects on the screen – album, performer, song. There are two ways of navigating towards previous screen – either by clicking backwards, which is offered by the OS as a standard navigation method, or by clicking in the top left corner, which is a possibility offered by the app. The second option is in accordance with the standards defined by Google [1]. One way navigation exists only from the screen for loading towards the media library. This screen is not part of the navigation process. It appears only when loading the initial information. All other navigations are bi-directional allowing the user to change the screens successively (as shown in fig 1) and to go back to the previous screen.

 Possibility to play songs from the phone memory;  Possibility for listing the song available, sorting them by a different criteria such as Performer, Album, all.  Possibility to extract detailed information about a given performer or album and for it visualization;  Loading and visualization of ID3 Tag information from the songs.  Loading the album cover (if available) from the song  Possibility for sharing of songs. The user interface (UI) is consistent to the standards of Android OS and the guidelines published by Google are followed in order to achieve good user experience (UX) [1]. The app is made of several screens showing various type of information to the user and giving him the

14

CAx Technologies, issue 3, December 2015, ISSN 1314-9628 loaded. The screen disappears from the stack and the user cannot go back to it by clicking on the back arrow. This is the only screen that the user cannot reach manually. It consist only of text informing the user that the information is being loaded.

Fig. 1 Screens and navigation model of the app

2. REALIZATION Playing songs is the main functionality. For the realization of this functionality Media Player class is used offered by Android. [2]. Android supports local SQLite database for files which are located on the device as well as information about them. With the help of services working in background mode and tracking for file change, this information is being updated and it is certain that the information is up to date. The OS offers an interface for this DB, through which information about the songs on the device could be retrieved. Android offers interface for loading album covers. They load either form the song file (only for some audio formats), from the internet, or from the folder in which the song is placed. The logic for choosing the source of the album cover is hidden for the programmer but for their loading a useful API is offered. By using the API, the functionality for the visualization of album covers is realized. Sharing of songs is not a very popular functionality among audio players. According to the authors this is a useful addition to the standard app functionalities. This functionality is realized by using the standard methods of sharing information between apps, while apps that have been already installed on the phone are used for integration with different social services. 2.1. Loading Screen The loading screen appears on start up. It remains visible for the user while necessary information is loaded in order for the player to function – songs, performers and albums. Once the information is loaded, the loading screen is closed automatically and the media library is

Fig. 2 Loading Screen The main thread of the app is called “Main”. All operations connected to the UI are deployed on it. This is why sometimes in literature it is called UI thread. It is extremely important this thread to be blocked as rarely as possible. It should be used for operation related to the UI (change of text color, showing dialog, clicking on a button etc.) and if possible - nothing more. All slow operations must be performed on a separate thread. In most cases such operations are IO – reading and writing in db, working with Internet, file processing, etc. Android tools used for app development are intelligent enough to perform static analysis of the code and to detect if there is such a code that performs IO operations on the main thread and to alarm with error when those appear. 2.2. Media Library Screen Once all the information is loaded, the media library screen appears. (fig.3). It consists of three tabs which present to the user the information

15

CAx Technologies, issue 3, December 2015, ISSN 1314-9628 the performer is considered as “undefined” and is added to a category with the same name. The second tab is similar to the first one, but it sorts the songs by a different criteria – album. The information is taken again from ID3 Tag fields in the song. In case this field is empty, the song is automatically added to an album entitled “undefined”. The third tab does not sort the songs by any criteria but it just visualizes all the songs (the so called flat format of data or just flat). This way the user has the possibility to view the available song without the need to navigate through the different performers or albums.

about the available songs in three different ways. The sorting of files is based on ID3 information available in the audio files. Switching between tabs is done by sliding in the opposite direction. For example, if we want to navigate from the first to the second tab, we would need to slide the screen from right to left. The first tab show the available music sorted by performer. The information is shown in the form of a table with two columns. Each cell presents a square whose background is an image related to the performer and a label in the bottom which shows the performer’s name. In the absence of an image, the default note image is visualized. If information about the performer in ID3 Tags is missing, then

Fig. 3 The three media library screen tabs. Visualization of the songs sorted by performer, album and list without sorting submitted to the class, which should work with such data. The use of this approach is widely spread as it isolates the logic for access to the data in the adapter and offers a unified interface for working with the data. This facilitates the integration of the adapter into the component. Since the information in each tab is different, there are separate adaptors for each tab but part of the logic is again exported in a basic class as the logic is common. The class is called AbsLibraryAdapter and is responsible for several main things as follows:

The logic in the three tabs is similar – the available information is loaded and then sorted by a given criteria. This gives the opportunity for the information to be gathered and reused through the abstract class AbsRecyclerViewFragment. Each tab contains one component – a list that shows the information. In our case GridLayoutManager and LinearLayoutManager are used, which render the elements in the list in the forms of a table and list accordingly. The other method, which is defined in the same class, is setAdapter(). Thus, in that case, in order to visualize the data in the list, an adapter should be

16

CAx Technologies, issue 3, December 2015, ISSN 1314-9628  It defines a mechanism for the processing of the events over the elements;  It implements the standard methods for connection with the list component (RecyclerView), used in the tabs for visualizing the information.  It provides the possibility to the successive classes to define how exactly the elements in the list will look like.

and the other one about an album. Figure 4 shows how the screens look like.

The components that show big quantity of data on the screen, by using scrolling, such as RecyclerView, which is used, works in the following way: Each element that is visualized on the screen is a separate instance of the component. For example, in case 1000 elements must be shown, this means that there should be 1000 instances of a given component. This would cost a lot of resources – e.g. memory, CPU time and battery. The optimization that could be done is to have the already created components to be reused. This becomes possible as at a given time only a small amount of them is visualized on the display. Thus, if only 10 elements are shown on the display, it is not necessary to instance all the 1000 elements but only part of them but this part shall not be less than 10 elements. Reusing of components consists in that when a new element should be shown on the screen, there is need to create a new element, but one that is no longer visible is taken and only the data in that element is changed. The number of components used is controlled by the OS. Every tab uses its own adaptor in which it has to implement the two abstract methods declared in the AbsLibraryAdapter class. 2.3. Details Screen When pushing certain visual components of the media library the details screen is launched. It can visualize details about a performer or an album. The idea of the screen is to show part of the available information about the component such as performer, album year, number of songs, album length, track list or the performer’s albums. At the top left corner one could see the backward arrow navigating to the previous screen. When choosing some the elements in the list the player is launched and the now playing screen is shown. When the user choses a particular song it is only that song that is loaded in the now playing list and when choosing an album, the entire album loads up. Buttons for choosing to play the entire album or all albums of the performer are available, which are made to facilitate user’s operation with the app. In fact, the details screen are two, one of them showing the info about a given performer

Fig. 4 Details screen used for performers (on the left) and for albums (on the right) The structure of the two screens is the same – consisting of a main component giving the info about the album or the performer on the one hand, and a list with the data contained in it on the other. The common logic is again extracted in a basic class (AbsDetailsActivity), which declares two abstract methods, which the successors must implement. Those are getAdapter() and getTitleString(). They are used for loading the adapter’s instance. The adaptors also have a common logic and it is moved into a basic class AbsDetailsHeaderAdapter. It is responsible for the structure appearing on the screen and adds the component with the details by giving the possibility to the successors simply to fill in the data. In addition, it declares interfaces for processing different events related to the screen such as pushing the buttons “Play All”, “Shuffle All”. 2.4. Now Playing Screen The Now playing screen (fig.5) gives the user the possibility to control the playing of the songs, to share now playing song and to get information about it and about the loaded songs. At top left corner a button for going backwards is placed. This could be either the Details Screen or media library depending on from which screen the now playing screen was launched. The sharing button is situated in the top right corner. By choosing it the user can share via e-mail, SMS or another application, information about what is being currently played. At the bottom part of the screen the player controls are located. Right above them is the song progress bar and above it is the album

17

CAx Technologies, issue 3, December 2015, ISSN 1314-9628 cover. The user has the option of changing the song by sliding the cover left or right accordingly in order to choose next or previous song. A song playlist is situated on the left. At first it is hidden for the user. In order for it to be visible it should be slided. Once it is opened the user can check which is the now playing song, what the next songs are or to choose a random song. This is the app’s most sophisticated screen. It gives the user the possibility to control the player by choosing songs, to change their order, etc. It consists of several parts:  Title – located in the upper side of the screen. It contains info about the now playing song and performer and a sharing button.  Album cover – it takes almost the whole screen by visualizing the cover of the album from which the now playing song is taken. If such cover is not available a default image is visualized (a note). The user can change the songs by sliding.  Song Progress Bar – it is located in the bottom end of the screen and contains a number buttons to control the music.  Pause/Play button  Previous Song button  Next Song button.  Changing the song order button – changes the songs order from alphabetic to shuffle and vice versa.  Repeat button – changes the way the songs are played by choosing whether to repeat them from the start or not.  Song progress bar – placed right above the buttons and allows the user to follow the progress of the current song and to change it manually.  Tracklist – this is a list of the songs being played in their default order. The tracklist is not visible by default but it should be slided from the left part of the screen. By using it, the user could do the following: - See what the now playing song is – it is shown in a different font from the others. - Change the nowplaying song by pressing on some of the others. - To add songs to the Play queue by pressing continuously on one of them. The songs added to the Play queue are played right after the now playing song. After all the songs in the Play queue are played, the playing goes back to the initial tracklist.

Fig. 5 Now playing screen – normal view (on the left), tracklist (middle) and sharing option (right) The class that this screen represents is PlayerActivity. There can be found the logic for manipulating the song playing, the buttons and the song switch. However, the logic for song playing is not located in that class. There are two major reasons for that:  The playing of the songs must be done in background mode or the main tread responsible for the visualization and the update of the user interface components would become not responding.  In accordance with the good design standards, each component must be responsible for one single element only. This class is responsible for this screen only and it would not be advisable for it to be involved in the song playing as this would lead to complicating the logic in the class as well as to a dependency between that class and the others in the app. In order to keep the good modularity and not to overload unnecessarily the main tread, the logic for playing the songs is moved into another component – service. The communication with it takes place via MediaPlayerClient class. The PlayerActivity class contains instance of MediaPlayerClient and uses most of its methods. In order for the client to function properly it must be sure that the service of the player is working. For that reason, whenthe screen is created, the client initializes and the service is launched. In addition, an observer is registered, that should supervise for changes in the song playing. Since

18

CAx Technologies, issue 3, December 2015, ISSN 1314-9628 the result is considered as Object type, in order to ensure that ClassCastException errors will not appear during the performance, it is recommended to check if the object is actually a State type object. In case the object is really a State type object, then the processing of information can continue. The current song is taken and it is checked if it is different form null. In case it is a null, this means that the song list is empty. In case the list is not null that means that there are songs in the list and the sections with new information could be populated. Those sections consist of: - the screen title that shows the song title and the performer; - the song progress bar; - the album cover. The last thing that is done is the refresh of the start/stop button’s state. Another important component of this screen is the album cover. At first glance this is a simple component whose only purpose is to show an image on the screen but it actually does much more. Besides the visualization of the cover, logic for changing the song is also implemented. When sliding the album cover, the song is changed with next or previous one. For the realization of this functionality ViewPager component is being used. It makes the creation of similar components easier by taking the implementation down to adapter and animation. The adapter is implemented as an internal class for PlayerActivity. The other function of this component is to process the sliding and to change the songs. This functionality is realized by adding OnPageChangeListener object to the ViewPager component, which observes for the sliding of the component. The two methods which perform the logic are onPageScrollStateChanged and onPageSelected. The first one tracks when the user actually slides the song and marks this with a flag in the class, and the second one calls the song change based on the direction towards which the sliding has been done. 2.5. Notification In order to have a good UX the app uses also notifications through which the user can control the player without the need for it to be the active app. After launching a song a notification appears in the status bar. (fig. 6). It contains information about the now playing song and control buttons previous song, next song, play/pause. The notifications are messages that show-up to the user outside the app screen. They consist of 2 parts – an icon and a visual component. The icon

appears in the status bar of the OS informing the user of a new notification. The visual component is the body of the notification. In order to build a notification, Notification.Builder class is used. This is a class that creates and configures a notification on the basis of the information sent to it. The notifications have minimized and extended view. The extended format is used when the notification is chosen; otherwise it is the minimized view that is used. This allows for a bigger number of notifications to be visualized in the notification area. Not every notification supports extended view. In order to support it, the setStyle method from the Builder class should be expressly called, which method accepts instance of Notifcation.Style class. This class has several direct successors, which various styles of extended view. They cover a large amount of cases in where the use of extended view is needed. To update a notification, its unique ID is used. This ID is set during its creation and it is unique in the context of the other notifications.

Fig. 6 Minimized (left) and extended (right) notification of the player Fig. 6 shows how the notification of the player looks like in minimized and extended view. It is created by the createNotification() method. Firstly, 4 objects of PendingIntent type are created. This is an object which contains a normal Intent, but it is not sent to the OS immediately but only when certain event occurs, related to the notification, e.g. clicking on the notification. There are four such objects for the following buttons accordingly:

19

CAx Technologies, issue 3, December 2015, ISSN 1314-9628    

class from the standard Android library which gives the option of extracting the information from SQLite or other sources of information.

Previous song button Pause/play button Next song button View whole notification button

For building the cursor query() has been used by giving as parameters the Uniform Resource Identifier, the columns that should be read, and, the criteria through which the data will be sorted. The work interface advisedly reminds of a normal SQL, in order to be easy to use. After the creation of the cursor, its content is perambulated and objects type Song, Album and Artist are created. They are classes defined in the app. Once the whole information is loaded and transformed into objects the cursor is closed calling the close() method in order to free up the resources reserved by it.

By using the Notification.Builder class a new notification is created by consequently configuring the following settings:  Icon, that will appear in the status bar;  Vibrations and sound notifications are forbidden when updating the notification;  PendingIntent obect is set-up, which will launch when clicking on the notification.  Adding a button for going back to the previous song  Adding a button for pause/play the song  задаваме PendingIntent обект, който да се изпълни при натискане на известието  Adding a button for choosing the next song  Setting up the notification’s visibility to public as it does not contain sensitive information;  Setting up the style of the extended notification to be MediaStyle  Prohibiting to show the date of the last notification update;  Launching the task that will update the album cover in the notification.

3. COCLUSION On the basis of the above observations of the realization and the experimental results it may be concluded that the following tasks are completed successfully:  The creation of an app for Android OS, by using Java programming language and Eclipse environment for development.  The app follows the good practices and standards for code defined by Google.  The app is with a clear UI design and a high level of UX according to the standards defined by Google.  Implemented are the navigation model and the screens  Playing songs from the phone’s memory in active mode, as well as in background mode, by simply using the program interface provided by Android.  Loading the songs available on the device by using the standard mechanisms provided by the OS.  Possibility to review the available songs on the device sorting by different criteria – performer or album.  Extraction of detailed information about performers, albums and songs from ID3 Tag information of the songs (if available) and its visualization to the user.  Loading the album cover by using the standard mechanisms developed by Android.  Possibility for sharing songs by using external apps already installed on the device.

Each time the player status is changed, the notification is updated. This occurs via the method updateNotification(). This method’s logic is based on the one related to the createNotification() method and for the update itself the system class NotificationManager is used. 2.6. Loading data Loading data for the songs is one of the main operations related to the app. Android uses SQLite DB where it holds information about all files available on the device. This way it can inform the user about the type of files and about the amount of space it takes in the memory. The information is accessible to all apps installed on the device. Andorid offers a user friendly interface that gives the option to search for different file types into the DB and to sort them by different criteria. The loading takes place in ContentLoader class. This class offers a single public method loadContent() that gives back a result in the form of Content type object.The Content class is optimized for working with data about songs, albums and performers. In loadContent() the Cursor class is used. This is a

20

CAx Technologies, issue 3, December 2015, ISSN 1314-9628 REFERENCES: 1. Meier R., Android Application Development (3rd Edition), Wrox, 2012, ISBN 978-1-118-10227-5 2. Darwin I., Android Cookbook, 2012, O'Reilly Media, ISBN 978-1-4493-8841-6

21