Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] share ayah as audio #2011

Closed
wants to merge 13 commits into from
4 changes: 3 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,11 @@
android:authorities="@string/file_authority"
android:grantUriPermissions="true"
android:exported="false">
tools:replace="android:authorities">
Copy link
Contributor

Choose a reason for hiding this comment

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

why did we need to add this?

<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
android:resource="@xml/file_paths"
tools:replace="android:resource" />
Copy link
Contributor

Choose a reason for hiding this comment

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

and this

</provider>

<receiver android:name="androidx.media.session.MediaButtonReceiver">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ constructor(private val quranDisplayData: QuranDisplayData,
lastAudioRequest?.let { play(it) }
}

private fun getDownloadIntent(context: Context, request: AudioRequest): Intent? {
fun getDownloadIntent(context: Context, request: AudioRequest): Intent? {
val qari = request.qari
val audioPathInfo = request.audioPathInfo
val path = audioPathInfo.localDirectory
Expand Down
295 changes: 278 additions & 17 deletions app/src/main/java/com/quran/labs/androidquran/ui/PagerActivity.java

Large diffs are not rendered by default.

107 changes: 105 additions & 2 deletions app/src/main/java/com/quran/labs/androidquran/util/AudioUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,25 @@ package com.quran.labs.androidquran.util

import android.content.Context
import android.content.Intent
import android.media.MediaMetadataRetriever
import android.net.Uri
import androidx.annotation.VisibleForTesting
import androidx.core.content.ContextCompat.startActivity
import androidx.core.content.FileProvider
import com.quran.data.core.QuranInfo
import com.quran.data.model.SuraAyah
import com.quran.labs.androidquran.common.audio.model.AudioConfiguration
import com.quran.labs.androidquran.common.audio.model.QariItem
import com.quran.labs.androidquran.common.audio.util.QariUtil
import com.quran.labs.androidquran.dao.audio.AudioPathInfo
import com.quran.labs.androidquran.service.AudioService
import com.quran.labs.androidquran.ui.PagerActivity
import com.quran.labs.androidquran.util.audioConversionUtils.CheapSoundFile
import timber.log.Timber
import java.io.File
import java.util.Locale
import java.io.*
import java.util.*
Copy link
Contributor

Choose a reason for hiding this comment

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

please let's not use star imports

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have fixed this in the latest commit

import javax.inject.Inject
import kotlin.math.roundToInt

class AudioUtils @Inject constructor(
private val quranInfo: QuranInfo,
Expand Down Expand Up @@ -283,6 +291,101 @@ class AudioUtils @Inject constructor(
}
}

fun getLocalAudioPathInfo(qari: QariItem): AudioPathInfo? {
val localPath = getLocalQariUrl(qari)
if (localPath != null) {
val databasePath = getQariDatabasePathIfGapless(qari)
val urlFormat = if (databasePath.isNullOrEmpty()) {
localPath + File.separator + "%d" + File.separator +
"%d" + AUDIO_EXTENSION
} else {
localPath + File.separator + "%03d" + AUDIO_EXTENSION
}
return AudioPathInfo(urlFormat, localPath, databasePath)
}
return null
}

fun getMergedAudioFromSegments(segments: ArrayList<String>): String {
var mergedAudioPath = segments[0]
if (segments.size > 1) {
for (i in 1 until segments.size) {
mergedAudioPath = mergeAudios(mergedAudioPath, segments[i])!!
}
}
return mergedAudioPath
}

private fun mergeAudios(path1: String, path2: String): String? {
val tempAudioName = UUID.randomUUID().toString() + ".mp3"
val destFile = File(PagerActivity.audioCacheDirectory.path + File.separator + tempAudioName)
try {
val fileInputStream = FileInputStream(path1)
val bArr = ByteArray(1048576)
Copy link
Contributor

Choose a reason for hiding this comment

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

constant - also what's relevant about this number here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is 1 MB (1024*1024 bytes), but I have removed this in favor of "Okio"

val fileOutputStream = FileOutputStream(destFile)
while (true) {
val read = fileInputStream.read(bArr)
if (read == -1) {
break
}
fileOutputStream.write(bArr, 0, read)
fileOutputStream.flush()
}
fileInputStream.close()
val fileInputStream2 = FileInputStream(path2)
while (true) {
val read2 = fileInputStream2.read(bArr)
if (read2 == -1) {
break
}
fileOutputStream.write(bArr, 0, read2)
fileOutputStream.flush()
}
fileInputStream2.close()
fileOutputStream.close()
Copy link
Contributor

Choose a reason for hiding this comment

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

we have okio in the code that might simplify this logic

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

return destFile.path
} catch (e2: FileNotFoundException) {
e2.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
}
return null
}

fun getSurahSegment(path: String, lowerCut: Int, upperCut: Int): String? {
if (lowerCut == 0 && upperCut == 0) {
return null
}
val tempAudioName = UUID.randomUUID().toString() + ".mp3"
val destFile = File(PagerActivity.audioCacheDirectory.path + File.separator + tempAudioName)
val mSoundFile = arrayOfNulls<CheapSoundFile>(1)
Copy link
Contributor

Choose a reason for hiding this comment

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

nit - please avoid m prefix on variables

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

try {
mSoundFile[0] = CheapSoundFile.create(path, null)
val startTime = lowerCut.toFloat() / 1000
val endTime = upperCut.toFloat() / 1000
val samplesPerFrame = mSoundFile[0]?.samplesPerFrame
val sampleRate = mSoundFile[0]?.sampleRate
val avg = sampleRate?.div(samplesPerFrame!!)
val startFrames = (startTime * avg!!).roundToInt()
val endFrames = (endTime * avg).roundToInt()
mSoundFile[0]?.WriteFile(destFile, startFrames, endFrames - startFrames)
} catch (e: IOException) {
e.printStackTrace()
}
return destFile.absolutePath
}

fun getSurahDuration(context: Context,path: String): Int {
val mmr = MediaMetadataRetriever()
mmr.setDataSource(context, Uri.parse(path))
val durationStr = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)
return durationStr!!.toInt()
}

fun getSurahAudioPath(audioPathInfo: AudioPathInfo, surah: Int): String? {
return String.format(Locale.US, audioPathInfo.urlFormat, surah)
}

companion object {
const val ZIP_EXTENSION = ".zip"
const val AUDIO_EXTENSION = ".mp3"
Expand Down
15 changes: 15 additions & 0 deletions app/src/main/java/com/quran/labs/androidquran/util/ShareUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,18 @@ import android.content.Context
import android.content.Intent
import android.widget.Toast
import androidx.annotation.StringRes
import androidx.core.content.ContextCompat
import androidx.core.content.FileProvider
import com.quran.data.model.QuranText
import com.quran.labs.androidquran.BuildConfig
import com.quran.labs.androidquran.R
import com.quran.labs.androidquran.common.LocalTranslation
import com.quran.labs.androidquran.common.QuranAyahInfo
import com.quran.labs.androidquran.data.QuranDisplayData
import com.quran.labs.androidquran.model.translation.ArabicDatabaseUtils
import com.quran.labs.androidquran.ui.util.ToastCompat
import dagger.Reusable
import java.io.File
import java.text.NumberFormat
import java.util.Locale
import javax.inject.Inject
Expand Down Expand Up @@ -124,4 +128,15 @@ class ShareUtil @Inject internal constructor(private val quranDisplayData: Quran
append("]")
}
}


fun shareAudioFileIntent(activity: Activity, file: File) {
val authorities = BuildConfig.APPLICATION_ID + ".fileprovider"
val uri = FileProvider.getUriForFile(activity, authorities, file)
val shareIntent = Intent(Intent.ACTION_SEND)
shareIntent.putExtra(Intent.EXTRA_STREAM, uri)
shareIntent.type = "audio/mp3"
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
activity.startActivity(Intent.createChooser(shareIntent, activity.getString(R.string.share_audio_file_title)))
}
}
Loading