Skip to content

Commit

Permalink
Merge pull request #21 from JanielGamer/development
Browse files Browse the repository at this point in the history
Development
  • Loading branch information
J4yJ4y-R6 authored Feb 2, 2021
2 parents 5944905 + 80377ae commit 91913dc
Show file tree
Hide file tree
Showing 78 changed files with 2,052 additions and 574 deletions.
75 changes: 75 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@

# Spotify Music Party

We made this Android application to provide a custom version of a MusicParty. Our idea was to set on simple Server-Client model, where only the Server is able to play the music.

## Installation
1. Go to the [Spotify Developer Page](https://developer.spotify.com/dashboard/) and create a application to get a. `Client ID` and a `Client Secret` (These will be needed if you wand to build the app local).
**Important:** You have to add your and fingerprint to the application in the developper page.
2. Clone the repository.
3. Rename the `apikey.properties.example` file to `apikey.properties` and add you previously gained `Client ID` and `Client Secret` at the right row inside the quotation marks.
4. Now you can use the default gradle build and debug commands.

### Android requirements
- `Android SDK >= 30`
- The spotify app has to be installed for hosting a server

## Functionalities

### Party-Owner
- You can become an owner by creating a MusicParty in the main menu.
- You can search for every song and artist available in Spotify by entering the value in the input at the top and clicking on the search button. You can add a song by swiping it in the result window.
- You can start, pause, skip a song or go back to the last song with the controls on under the album-cover on the main page.
- Queue: Toolbar 1. Button
- See the current state of the queue
- Change the playlist order by drag and drop
- Remove a song from the playlist by swiping it to the left
- Settings: Toolbar 2. Button
- Change the party name, which is displayed to everybody
- See your IP-Address and your Password to invite other people
- See a QR-Code which stores your IP-Address and Password for sharing
- Share information, QR-Code or a link for joining your party
- Change the party type (currently two options):
- All-In: All queued songs will be added to the playlist. Only you can edit the playlist.
- Voting: Every time someone wants to queue a song, a voting will automatically be created to decide whether the song will be added to the queue. Also there is always a voting to skip the currently playing song.
- Change voting time (only available in Voting-Mode)
- Voting: Toolbar 3. Button (only visible in Voting-Mode):
- See all currently open votings:
- Queue-Voting: A voting for every queue request
- Skip-Voting: Always one voting, while a song is currently playing, to skip this song
- You have three options for every voting-card:
- Thumb-Up: Vote Yes
- Thumb-Down: Vote No
- X-Button: Ignore
- Party-People: Toolbar 4. Button
- See everybody who is currently a part of your party
- Exit: Toolbar 5. Button
- Save all songs played at the party as a playlist in Spotify and add them to your favorites in our App.
- End the party. Everybody will be disconnected from the party.
- Favorite-Playlists: Heart-Button (top-right-corner)
- See a list of your saved playlists
- By clicking one of the playlist-cards you get three options:
- Playing the playlist, which will remove the current playlist state
- Remove the playlist from your favorites
- Edit the image or the name of your playlist. It will be changed in the MusicParty-App and in Spotify.


### Party-People
- You can become a Party-People by joining a currently open MusicParty by one of the following options:
- Enter IP-Address and Password in the input fields
- Scan a QR-Code which will fill the fields
- Use a link which will fill the fields
- You can enter a name or use a random generated one. Only the owner will see your name.
- You can search for every song and artist available in Spotify by entering the value in the input at the top and clicking on the search button. You can add a song by swiping it in the result window.
- Queue: Toolbar 1. Button
- See the current state of the queue
- Voting: Toolbar 2. Button (only visible in Voting-Mode):
- See all currently open votings:
- Queue-Voting: A voting for every queue request
- Skip-Voting: Always one voting, while a song is currently playing, to skip this song
- You have three options for every voting-card:
- Thumb-Up: Vote Yes
- Thumb-Down: Vote No
- X-Button: Ignore
- Exit: Toolbar 5. Button
- Leave the party
2 changes: 2 additions & 0 deletions apikey.properties.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CLIENT_ID = ""
CLIENT_SECRET = ""
53 changes: 35 additions & 18 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,55 +10,72 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18"/>
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />

<application
android:name="com.tinf19.musicparty.App"
android:name=".App"
android:allowBackup="true"
android:icon="@mipmap/ic_music_party_greenbg"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_music_party_greenbg_round"
android:supportsRtl="true"
android:theme="@style/Theme.MusicParty">
<receiver android:name="com.tinf19.musicparty.receiver.ActionReceiver" />
<receiver android:name=".receiver.ActionReceiver" />

<receiver android:name=".receiver.VotedReceiver"
android:enabled="true"
android:exported="true"/>


<service
android:name="com.tinf19.musicparty.client.ClientService"
android:name=".client.ClientService"
android:enabled="true"
android:exported="true" />
<service
android:name="com.tinf19.musicparty.server.HostService"
android:name=".server.HostService"
android:enabled="true"
android:exported="true" />


<activity
android:name="com.journeyapps.barcodescanner.CaptureActivity"
android:screenOrientation="portrait"
tools:replace="screenOrientation"/>
<activity android:name="com.tinf19.musicparty.client.ClientActivity"
android:screenOrientation="portrait"/>
<activity android:name="com.tinf19.musicparty.client.JoinActivity"
android:screenOrientation="portrait">
tools:replace="screenOrientation" />
<activity
android:name=".client.ClientActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan" />
<activity
android:name=".client.JoinActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan">
<intent-filter>
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Accepts URIs that begin with "example://gizmos” -->
<data android:scheme="http"
android:host="musicparty.join" />
<data
android:host="musicparty.join"
android:scheme="http" />
</intent-filter>
</activity>
<activity
android:name="com.spotify.sdk.android.auth.LoginActivity"
android:screenOrientation="portrait"
android:theme="@android:style/Theme.Translucent.NoTitleBar"/>
<activity android:name="com.tinf19.musicparty.server.HostActivity"
android:screenOrientation="portrait"/>
<activity android:name="com.tinf19.musicparty.MainActivity"
android:screenOrientation="portrait">
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
<activity
android:name=".server.HostActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan" />
<activity
android:name=".MainActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/com/tinf19/musicparty/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
Expand Down Expand Up @@ -51,6 +52,7 @@ protected void onCreate(Bundle savedInstanceState) {
setContentView(binding.getRoot());
binding.createPartyCardView.setEnabled(true);
binding.joinPartyCardView.setEnabled(true);
binding.textView6.setMovementMethod(LinkMovementMethod.getInstance());

SharedPreferences firstConnection = this.getSharedPreferences("firstConnection", Context.MODE_PRIVATE);
if(firstConnection.getBoolean(Constants.FIRST_CONNECTION, true)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;

import com.tinf19.musicparty.R;
import com.tinf19.musicparty.music.Track;
import com.tinf19.musicparty.util.Constants;
import com.tinf19.musicparty.util.DisplayMessages;
import com.tinf19.musicparty.util.DownloadImageTask;

import java.util.List;
Expand All @@ -36,6 +37,7 @@ public interface SearchSongOutputAdapterCallback {
private final SearchSongOutputAdapterCallback searchSongOutputAdapterCallback;
private List<Track> mDataset;
private View textView;
private Context context;


/**
Expand Down Expand Up @@ -95,7 +97,7 @@ public SearchSongsOutputAdapter(List<Track> trackList, SearchSongOutputAdapterCa
@NonNull
@Override
public SearchSongsOutputAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
Context context = parent.getContext();
context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
textView = inflater.inflate(R.layout.row_song_output, parent, false);
return new ViewHolder(textView);
Expand All @@ -105,7 +107,7 @@ public SearchSongsOutputAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
String name = mDataset.get(position).getName();
String artist = mDataset.get(position).getArtist(0).getName();
String cover = "https://i.scdn.co/image/" + mDataset.get(position).getCover();
String cover = Constants.IMAGE_URI + mDataset.get(position).getCover();
TextView songTitleTV = holder.songTitleTextView;
if(songTitleTV != null)
songTitleTV.setText(name);
Expand All @@ -116,7 +118,8 @@ public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
if(songCoverIV != null)
new DownloadImageTask(songCoverIV).execute(cover);
holder.itemView.setOnClickListener(v -> {
Toast.makeText(textView.getContext(), textView.getContext().getString(R.string.text_songsOutputSwipeForQue), Toast.LENGTH_LONG).show();
new DisplayMessages(context.getString(R.string.text_songsOutputSwipeForQue),
textView.findViewById(R.id.showSongHostFragmentFrame)).makeMessage();
});

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

import com.tinf19.musicparty.util.Constants;

import org.jetbrains.annotations.NotNull;

/**
* SearchSongsSoutputItemTouchHelper is managing the touch events in the RecyclerView of
* {@link com.tinf19.musicparty.fragments.SearchSongsOutputFragment}
Expand Down Expand Up @@ -35,7 +37,7 @@ public interface SearchSongOutputItemTouchHelperViewHolderCallback {
* @param adapter Adapter of the RecyclerView in {@link com.tinf19.musicparty.fragments.SearchSongsOutputFragment}
*/
public SearchSongsOutputItemTouchHelper(SearchSongOutputItemTouchHelperCallback adapter) {
mAdapter = adapter;
this.mAdapter = adapter;
this.adapter = (SearchSongsOutputAdapter) adapter;
}

Expand All @@ -59,17 +61,22 @@ public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull Recycle
}

@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) { return false; }
public boolean onMove(@NonNull RecyclerView recyclerView,
@NonNull RecyclerView.ViewHolder viewHolder,
@NonNull RecyclerView.ViewHolder target) {
return false;
}

@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
mAdapter.sendToPlaylist(viewHolder.getAdapterPosition());
adapter.notifyItemChanged(viewHolder.getAdapterPosition());

}

@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
public void onChildDraw(@NotNull Canvas c, @NotNull RecyclerView recyclerView,
@NotNull RecyclerView.ViewHolder viewHolder, float dX, float dY,
int actionState, boolean isCurrentlyActive) {
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
final float alpha = Constants.ALPHA_FULL - Math.abs(dX) / (float) viewHolder.itemView.getWidth();
viewHolder.itemView.setAlpha(alpha);
Expand All @@ -83,15 +90,17 @@ public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHo
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
if (viewHolder instanceof SearchSongOutputItemTouchHelperViewHolderCallback) {
SearchSongOutputItemTouchHelperViewHolderCallback itemViewHolder = (SearchSongOutputItemTouchHelperViewHolderCallback) viewHolder;
SearchSongOutputItemTouchHelperViewHolderCallback itemViewHolder =
(SearchSongOutputItemTouchHelperViewHolderCallback) viewHolder;
itemViewHolder.onItemSelected();
}
}
super.onSelectedChanged(viewHolder, actionState);
}

@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
public void clearView(@NotNull RecyclerView recyclerView,
@NotNull RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);

viewHolder.itemView.setAlpha(Constants.ALPHA_FULL);
Expand Down
Loading

0 comments on commit 91913dc

Please sign in to comment.