Music Buddy is a social networking app designed to help users find and make friends based on their music taste!
Music Buddy utilizes Spotify API to analyze user data and connect users based on similar music taste.
- Category: Social/Music
- Mobile: Android
- Story: Make friends through music
- Market: Social media users
- Habit: Match, and get to know more users with the same music taste
- Scope: Create an app which allows users to create new connections, chat with friends, and see what artists their friends are listening to
Required Must-have Stories
- User must be able to login with Oauth Spotify
- User can see potential new matches in the main feed with the option to add or decline
- Have a friends page with people matched
- User can see friends’s top 3 artist
- Have a Profile page showing more details about the user
- Have a chat list with displaying a list of friends
- Users are able to chat with friends they have matched with
- Settings page where they can set their bio, approximate location, and age
Optional Nice-to-have Stories
- More detailed location setting
- Have notifications for new messages
- Matched friends are sorted by unmet first
- Add activity to see trending artists/songs and which friends are listening
- Listen along with friends if they are listening to something currently
- User can set their own profile picture instead of their spotify one in their preferences
- User can log out
- Have Sync chat
- Open youtube videos inside chat
- Login
- User must be able to login with Oauth Spotify
- Home
- User can see potential new matches in the main feed with the option to add or decline
- Friends
- Have a friends page with people matched
- User can see friends’s top 3 artist
- [Optional] Add activity to see trending artists/songs and which friends are listening
- [Optional] Listen along with friends if they are listening to something currently
- Profile
- Have a Profile page showing more details about the user
- [Optional] User can log out
- Settings
- Settings page where they can set their bio, approximate location, and age
- [Optional] More detailed location setting
- [Optional] User can set their own profile picture instead of their spotify one in their preferences
- Chat list
- Have a chat list with displaying a list of friends
- [Optional] Matched friends are sorted by unmet first
- Chat Message
- Users are able to chat with friends they have matched with
- [Optional] Have notifications for new messages
- [Optional] Have Sync chat
- [Optional] Open youtube videos inside chat
Tab Navigation (Tab to Screen)
- Home
- Friends
- Chat List
** Flow Navigation** (Screen to Screen)
- Login
- Preferences
- Home
- Friends
- Profile
- Chat Message
- Chat List
- Chat Message
- Profile
- Settings
GIF created with LiceCap.
| Property | Type | Description |
|---|---|---|
| objectId | String | unique id for the user (default field and auto) |
| username | String | name the user chooses from spotify or create in the app when first sign in |
| userAge | int | user age |
| location | String | the state where the user is located |
| profilePic | File | user profile pic from spotify or uploaded himself/herself |
| profileDescription | String | User bio/description |
| invites | User[] (array of userID) | invites an user has |
| friends | User[] (array of userID) | friends an user has |
| createdAt | DateTime | date when User is created (default field) |
| lastSwiped | int | Highest userID seen |
| customPic | Boolean | True if user wants their custom picture chosen |
| Property | Type | Description |
|---|---|---|
| objectId | String | unique id for conversations (default increasing) |
| userOne | String | this is the id of the user that is going to send the message |
| userTwo | String | this is the id of the user that is going to get the message |
| chatText | String | this is the actual content of the chat (for example 'hi, how are you') |
| createdAt | DateTime | date when User is created (default field) |
-
Home
- (Read/Get) Query last swiped
val query = ParseQuery<ParseObject>("Profile") query.whereMatches("userID") query.selectKeys(java.util.List.of("lastSwiped")) query.findInBackground { objects: List<ParseObject>, e: ParseException? -> if (e == null) { Log.d(Companion.TAG, "Objects: $objects") Log.d(Companion.TAG, "Object name: " + objects[0]["lastSwiped"]) } else { Log.e(Companion.TAG, "Parse Error: ", e) } }
- (Create/Post) Add userID in User invite array
val query = ParseQuery<ParseObject>("Profile") query.whereMatches("userID") query.selectKeys(java.util.List.of("invites")) query.adddInvite(otherUserID) query.saveInBackground { objects: List<ParseObject>, e: ParseException? -> if (e == null) { Log.d(Companion.TAG, "Objects: $objects") Log.d(Companion.TAG, "Object name: " + objects[0]["invites"]) } else { Log.e(Companion.TAG, "Parse Error: ", e) } }
- (Create/Post) Remove userID in User invite array
val query = ParseQuery<ParseObject>("Profile") query.whereMatches("userID") query.selectKeys(java.util.List.of("invites")) query.removeInvite(otherUserID) query.saveInBackground { objects: List<ParseObject>, e: ParseException? -> if (e == null) { Log.d(Companion.TAG, "Objects: $objects") Log.d(Companion.TAG, "Object name: " + objects[0]["invites"]) } else { Log.e(Companion.TAG, "Parse Error: ", e) } }
- (Create/Post) Add userID in User friends array
val query = ParseQuery<ParseObject>("Profile") query.whereMatches("userID") query.selectKeys(java.util.List.of("friends")) query.addFriend(otherUserID) query.saveInBackground { objects: List<ParseObject>, e: ParseException? -> if (e == null) { Log.d(Companion.TAG, "Objects: $objects") Log.d(Companion.TAG, "Object name: " + objects[0]["friends"]) } else { Log.e(Companion.TAG, "Parse Error: ", e) } }
- (Read/Get) Query last swiped
-
Settings
- (Read/Get) Create picture for profile
val query = ParseQuery<ParseObject>("Profile") query.whereMatches("userID") query.selectKeys(java.util.List.of("profilePic")) query.setPicture(picture) query.saveInBackground { objects: List<ParseObject>, e: ParseException? -> if (e == null) { Log.d(Companion.TAG, "Objects: $objects") Log.d(Companion.TAG, "Object name: " + objects[0]["profilePic"]) } else { Log.e(Companion.TAG, "Parse Error: ", e) } }
- (Create/POST) Create description for profile
val query = ParseQuery<ParseObject>("Profile") query.whereMatches("userID") query.selectKeys(java.util.List.of("profileDescription")) query.setDescription(description) query.saveInBackground { objects: List<ParseObject>, e: ParseException? -> if (e == null) { Log.d(Companion.TAG, "Objects: $objects") Log.d(Companion.TAG, "Object name: " + objects[0]["profileDescription"]) } else { Log.e(Companion.TAG, "Parse Error: ", e) } }
- (Read/Get) Create picture for profile
-
Profile
- (Read/Get) Query user description
val query = ParseQuery<ParseObject>("Profile") query.whereMatches("userID") query.selectKeys(java.util.List.of("profileDescription")) query.findInBackground { objects: List<ParseObject>, e: ParseException? -> if (e == null) { Log.d(Companion.TAG, "Objects: $objects") Log.d(Companion.TAG, "Object name: " + objects[0]["profileDescription"]) } else { Log.e(Companion.TAG, "Parse Error: ", e) } }
- (Read/Get) Create picture for profile
val query = ParseQuery<ParseObject>("Profile") query.whereMatches("userID") query.selectKeys(java.util.List.of("profilePic")) query.setPicture(picture) query.saveInBackground { objects: List<ParseObject>, e: ParseException? -> if (e == null) { Log.d(Companion.TAG, "Objects: $objects") Log.d(Companion.TAG, "Object name: " + objects[0]["profilePic"]) } else { Log.e(Companion.TAG, "Parse Error: ", e) } }
- (Read/Get) Query username
val query = ParseQuery<ParseObject>("Profile") query.whereMatches("userID") query.selectKeys(java.util.List.of("useername")) query.findInBackground { objects: List<ParseObject>, e: ParseException? -> if (e == null) { Log.d(Companion.TAG, "Objects: $objects") Log.d(Companion.TAG, "Object name: " + objects[0]["username"]) } else { Log.e(Companion.TAG, "Parse Error: ", e) } }
- (Read/Get) Query user description
-
Friends
- (Read/Get) List of users friends
val query = ParseQuery<ParseObject>("Profile") query.whereMatches("userID") query.selectKeys(java.util.List.of("friends")) query.findInBackground { objects: List<ParseObject>, e: ParseException? -> if (e == null) { Log.d(Companion.TAG, "Objects: $objects") Log.d(Companion.TAG, "Object name: " + objects[0]["friends"]) } else { Log.e(Companion.TAG, "Parse Error: ", e) } }
- (Read/Get) List of users friends
-
Chat List
- (Read/Get) List of friends
val query = ParseQuery<ParseObject>("Profile") query.whereMatches("userID") query.selectKeys(java.util.List.of("friends")) query.findInBackground { objects: List<ParseObject>, e: ParseException? -> if (e == null) { Log.d(Companion.TAG, "Objects: $objects") Log.d(Companion.TAG, "Object name: " + objects[0]["friends"]) } else { Log.e(Companion.TAG, "Parse Error: ", e) } }
- (Read/Get) Query username
val query = ParseQuery<ParseObject>("Profile") query.whereMatches("userID") query.selectKeys(java.util.List.of("username")) query.findInBackground { objects: List<ParseObject>, e: ParseException? -> if (e == null) { Log.d(Companion.TAG, "Objects: $objects") Log.d(Companion.TAG, "Object name: " + objects[0]["username"]) } else { Log.e(Companion.TAG, "Parse Error: ", e) } }
- (Read/Get) Query pic
val query = ParseQuery<ParseObject>("Profile") query.whereMatches("userID") query.selectKeys(java.util.List.of("profilePic")) query.findInBackground { objects: List<ParseObject>, e: ParseException? -> if (e == null) { Log.d(Companion.TAG, "Objects: $objects") Log.d(Companion.TAG, "Object name: " + objects[0]["profilePic"]) } else { Log.e(Companion.TAG, "Parse Error: ", e) } }
- (Read/Get) List of friends
-
Chat Message
- (Read/Get) Query username
val query = ParseQuery<ParseObject>("Profile") query.whereMatches("userID") query.selectKeys(java.util.List.of("username")) query.findInBackground { objects: List<ParseObject>, e: ParseException? -> if (e == null) { Log.d(Companion.TAG, "Objects: $objects") Log.d(Companion.TAG, "Object name: " + objects[0]["username"]) } else { Log.e(Companion.TAG, "Parse Error: ", e) } }
- (Read/Get) Query chat messages
val query = ParseQuery<ParseObject>("userChat") query.whereMatches("userID") query.whereMatches("friendID") query.addDescendingOrder("objectId"); query.findInBackground { objects: List<ParseObject>, e: ParseException? -> if (e == null) { Log.d(Companion.TAG, "Objects: $objects") Log.d(Companion.TAG, "Object name: " + objects[0]["chat"]) } else { Log.e(Companion.TAG, "Parse Error: ", e) } }
- (Create/POST) Create new chat message
val query = ParseQuery<ParseObject>("userChat") query.whereMatches("userID") query.whereMatches("friendID") query.setMessage(message) query.saveInBackground { objects: List<ParseObject>, e: ParseException? -> if (e == null) { Log.d(Companion.TAG, "Objects: $objects") Log.d(Companion.TAG, "Object name: " + objects[0]["chat"]) } else { Log.e(Companion.TAG, "Parse Error: ", e) } }
- (Read/Get) Query username
-
Base URL - https://api.spotify.com/v1
HTTP Verb Endpoint Description GET/me/top/type Get User's Top Items GET/users/user_id Get User's Profile GET/me Get Current User's Profile GETme/player Get Playback State GETme/following Get Followed Artists GETme/following/contains Check If User Follows Artists or Users
- Create top app bar
- Create Parse Page
- Create bottom XML navigation bar
- Create Simple XML Template for the Homepage
- Create Profile and Home XML
- show location (state) selection in Settings page
- Ability to select user age in settings page
- User can create a bio in the settings page
- Use spotify API to allow user to use OAuth Authentication
- Created fragment manager in main activity
- (Backend) Update data from Setting to Parse
- Created friend list fragment in chat list
- Created friends screen horizontal friends display fragment
- Created fragment manager in main activity
- Create Chat xml Fragment
- (Backend) Query List of users friends
- Implement Chat List
- Implement Parse Classes for User, userData and userChat
- Improved Chat List to include only friends.
- Created Adapter for chat messages
- Created Fragment for chat messages.
- User can see last chat message received from friend in chat list.
- Ability to send messages.
- Ability to get all messages between chosen user.
- Added time stamp of how long ago the message was sent.
- Added swipe to refresh messages.
- Improved login process to only login when parse user is logged in.
---- All GIFs are created with [LiceCap](http://www.cockos.com/licecap/).












