Skip to content
This repository has been archived by the owner on Jan 31, 2024. It is now read-only.

Implemented downloading features #155

Merged
merged 6 commits into from
Apr 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package ch.sdp.vibester.activity

import android.content.Intent
import android.view.View
import androidx.test.core.app.ActivityScenario
import androidx.test.core.app.ApplicationProvider
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.*
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.intent.Intents
import androidx.test.espresso.matcher.ViewMatchers.*
import androidx.test.ext.junit.rules.ActivityScenarioRule
import ch.sdp.vibester.R
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import java.io.File

class DownloadActivityTest {

@Rule
@JvmField
val activityRule = ActivityScenarioRule(DownloadActivity::class.java)

@Before
fun setUp() {
Intents.init()
}

@After
fun clean() {
Intents.release()
}

private var waitForButton: Long = 100
private var waitForDownload: Long = 2000

@Test
fun downloadCorrectSong() {
val intent = Intent(ApplicationProvider.getApplicationContext(), DownloadActivity::class.java)
val scn: ActivityScenario<DownloadActivity> = ActivityScenario.launch(intent)
val songName = "imagine dragons believer"

onView(withId(R.id.download_songName)).perform(typeText(songName), closeSoftKeyboard())
Thread.sleep(waitForButton)
onView(withId(R.id.download_downloadsong)).perform(click())
Thread.sleep(waitForDownload)

onView(withId(R.id.download_songName)).check(matches(withText("")))
onView(withId(R.id.download_songName)).check(matches(withHint("Try another song!")))

val extract = File("storage/emulated/0/Download", "extract_of_$songName")
assert(extract.exists())
}

@Test
fun downloadIncorrectSong() {
val intent = Intent(ApplicationProvider.getApplicationContext(), DownloadActivity::class.java)
val scn: ActivityScenario<DownloadActivity> = ActivityScenario.launch(intent)
val songName = "adsfasdgyasdfa"

onView(withId(R.id.download_songName)).perform(typeText(songName), closeSoftKeyboard())
Thread.sleep(100)
onView(withId(R.id.download_downloadsong)).perform(click())
Thread.sleep(2000)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try using constants for the Thread.sleep calls instead of hardcoded values.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!


onView(withId(R.id.download_songName)).check(matches(withText("")))
onView(withId(R.id.download_songName)).check(matches(withHint("Please retry!")))

val extract = File("storage/emulated/0/Download", "extract_of_$songName")
assert(!extract.exists())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,10 @@ class WelcomeActivityTest {
onView(withId(R.id.welcome_settings)).perform(click())
intended(hasComponent(AuthenticationActivity::class.java.name))
}

@Test
fun checkIntentOnDownload() {
onView(withId(R.id.welcome_download)).perform(click())
intended(hasComponent(DownloadActivity::class.java.name))
}
}
4 changes: 4 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<application
android:name=".VibesterApp"
Expand All @@ -18,6 +19,9 @@
android:supportsRtl="true"
android:theme="@style/Theme.MyApplication"
android:usesCleartextTraffic="true">
<activity
android:name=".activity.DownloadActivity"
android:exported="false" />
<activity
android:name=".activity.CreateProfileActivity"
android:exported="false" />
Expand Down
135 changes: 135 additions & 0 deletions app/src/main/java/ch/sdp/vibester/activity/DownloadActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package ch.sdp.vibester.activity

import android.Manifest
import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Environment
import android.view.View
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import ch.sdp.vibester.R
import ch.sdp.vibester.api.ItunesMusicApi
import ch.sdp.vibester.model.Song
import okhttp3.OkHttpClient
import org.w3c.dom.Text
import java.lang.IllegalArgumentException
/*
* Activity that handles downloading of song extracts.
*/
class DownloadActivity : AppCompatActivity() {
private val STORAGE_PERMISSION_CODE = 1000
private lateinit var song: Song
private var songName: String = "imagine dragons believer"
private var downloadId: Long = 0

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_download)

val songNameView = findViewById<TextView>(R.id.download_songName)
val downloadButton = findViewById<Button>(R.id.download_downloadsong)

downloadButton.setOnClickListener {
songName = songNameView.text.toString()
val songFuture = ItunesMusicApi.querySong(songName, OkHttpClient(), 1)
try {
song = Song.singleSong(songFuture.get())
checkPermissionsAndDownload()
} catch (e: IllegalArgumentException) {
alert("Unable to find song, please retry!", "Please retry!", songNameView)
}
}

var broadcast = object:BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
var id = intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
if(id == downloadId) {
alert("Download completed!", "Try another song!", songNameView)
}
}
}

registerReceiver(broadcast, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
}

/*
* Displays a Toast on the screen while editing the existing textView.
*
* @param toast: String to be displayed on the Toast.
* @param hint : String to be set as the hint of the textView.
* @param view : The textView that will be updated.
*/
private fun alert(toast: String, hint: String, view: TextView) {
Toast.makeText(applicationContext, toast, Toast.LENGTH_LONG).show()
editTextView(hint, view)
}

/*
* Sets the hint of the given textview with the given hint, and clears the entered text.
*
* @param hint : String to be set as the hint of the textView.
* @param songNameView : The textView that will be updated.
*/
private fun editTextView(hint: String, songNameView: TextView) {
songNameView.text = ""
songNameView.hint = hint
}

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if(requestCode == STORAGE_PERMISSION_CODE) {
if(grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
downloadId = startDownload()
}
} else {
Toast.makeText(this, "Permission denied, cannot download!", Toast.LENGTH_LONG).show()
}
}

/*
* Checks if the required app permissions are already given. If not, request those permissions.
*/
private fun checkPermissionsAndDownload() {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
if(checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) {
requestPermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), STORAGE_PERMISSION_CODE)
} else {
downloadId = startDownload()
}
} else {
downloadId = startDownload()
}
}

/*
* Download a file from the private URL value of the class.
*/
private fun startDownload(): Long {
val request = DownloadManager.Request(Uri.parse(song.getPreviewUrl()))
request.setAllowedNetworkTypes(
DownloadManager.Request.NETWORK_MOBILE
or DownloadManager.Request.NETWORK_WIFI
)
.setTitle("extract_of_$songName")
.setAllowedOverRoaming(true)
.setDescription("Downloading extract of the song + $songName")
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
.setDestinationInExternalPublicDir(
Environment.DIRECTORY_DOWNLOADS,
"extract_of_$songName"
)

val downloader = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
return downloader.enqueue(request)
}
}
4 changes: 4 additions & 0 deletions app/src/main/java/ch/sdp/vibester/activity/WelcomeActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ class WelcomeActivity : AppCompatActivity() {
sendDirectIntent(AuthenticationActivity::class.java)
}

fun switchToDownload(view: View) {
sendDirectIntent(DownloadActivity::class.java)
}

Comment on lines +42 to +45
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be easy to test, currently untested

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

/*
* Belongs to a previously implemented button, taken out for UI purposes.
* Might bring it back, thus leaving the code for now.
Expand Down
35 changes: 35 additions & 0 deletions app/src/main/res/layout/activity_download.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.DownloadActivity">

<EditText
android:id="@+id/download_songName"
android:layout_width="253dp"
android:layout_height="50dp"
android:layout_marginTop="100dp"
android:layout_marginBottom="50dp"
android:ems="10"
android:hint="@string/download_songname"
android:inputType="textPersonName"
app:layout_constraintBottom_toTopOf="@+id/download_downloadsong"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="TextContrastCheck" />

<Button
android:id="@+id/download_downloadsong"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:text="@string/download_download"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/download_songName" />

</androidx.constraintlayout.widget.ConstraintLayout>
13 changes: 13 additions & 0 deletions app/src/main/res/layout/activity_welcome_screen.xml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,19 @@
android:translationZ="10dp"
app:icon="@android:drawable/ic_menu_manage" />

<Button
android:id="@+id/welcome_download"
android:layout_width="200dp"
android:layout_height="48dp"
android:layout_marginTop="10dp"
android:backgroundTint="@color/cg_blue"
android:elevation="10dp"
android:onClick="switchToDownload"
android:stateListAnimator="@null"
android:text="@string/welcome_download"
android:translationZ="10dp"
app:icon="@android:drawable/stat_sys_download" />

<Space
android:layout_width="match_parent"
android:layout_height="42dp" />
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@
<string name="editUsername">Edit Username</string>
<string name="editHandle">Edit Handle</string>
<string name="holder_setup_game_type">Choose the game you want to play:</string>
<string name="welcome_download">DOWNLOAD</string>
<string name="download_songname">Enter a song name...</string>
<string name="download_download">DOWNLOAD SONG</string>

<string name="Singleplayer">Singleplayer</string>
<string name="Multiplayer">Multiplayer</string>
Expand Down