Skip to content

Commit

Permalink
- Updated example app with support for shared storage
Browse files Browse the repository at this point in the history
- Bugs fixes
  • Loading branch information
AbedElazizShe committed Aug 15, 2020
1 parent bf37b7f commit eb12847
Show file tree
Hide file tree
Showing 9 changed files with 332 additions and 115 deletions.
1 change: 0 additions & 1 deletion .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions .idea/jarRepositories.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
xmlns:tools="http://schemas.android.com/tools"
package="com.abedelazizshe.lightcompressor">

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />

<application
android:allowBackup="true"
Expand Down
221 changes: 147 additions & 74 deletions app/src/main/java/com/abedelazizshe/lightcompressor/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ package com.abedelazizshe.lightcompressor
import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.content.ContentValues
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.os.Handler
import android.provider.MediaStore
import android.text.format.DateUtils
import android.util.Log
import android.view.View
Expand All @@ -19,14 +22,18 @@ import com.abedelazizshe.lightcompressorlibrary.VideoCompressor
import com.abedelazizshe.lightcompressorlibrary.VideoQuality
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.content_main.*
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException

/**
* Created by AbedElaziz Shehadeh on 26 Jan, 2020
* [email protected]
*/

class MainActivity : AppCompatActivity() {

companion object {
Expand Down Expand Up @@ -73,79 +80,80 @@ class MainActivity : AppCompatActivity() {
if (requestCode == REQUEST_SELECT_VIDEO) {
if (data != null && data.data != null) {
val uri = data.data
path = getMediaPath(this, uri)
val file = File(path)

mainContents.visibility = View.VISIBLE
GlideApp.with(this).load(uri).into(videoImage)

val downloadsPath =
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
val desFile = File(downloadsPath, "${System.currentTimeMillis()}_${file.name}")
if (desFile.exists()) {
desFile.delete()
try {
desFile.createNewFile()
} catch (e: IOException) {
e.printStackTrace()
}

}

var time = 0L

VideoCompressor.start(
path,
desFile.path,
object : CompressionListener {
override fun onProgress(percent: Float) {
//Update UI
runOnUiThread {
progress.text = "${percent.toLong()}%"
progressBar.progress = percent.toInt()
}

}

override fun onStart() {
time = System.currentTimeMillis()
progress.visibility = View.VISIBLE
progressBar.visibility = View.VISIBLE
originalSize.text = "Original size: ${getFileSize(file.length())}"
}

override fun onSuccess() {
val newSizeValue = desFile.length()

newSize.text =
"Size after compression: ${getFileSize(newSizeValue)}"

time = System.currentTimeMillis() - time
timeTaken.text =
"Duration: ${DateUtils.formatElapsedTime(time / 1000)}"

path = desFile.path

Handler().postDelayed({
progress.visibility = View.GONE
progressBar.visibility = View.GONE
}, 50)
uri?.let {
mainContents.visibility = View.VISIBLE
GlideApp.with(applicationContext).load(uri).into(videoImage)

GlobalScope.launch {
// run in background as it can take a long time if the video is big,
// this implementation is not the best way to do it,
// todo(abed): improve threading
val job = async { getMediaPath(applicationContext, uri) }
path = job.await()

val desFile = saveVideoFile(path)

desFile?.let {
var time = 0L
VideoCompressor.start(
path,
desFile.path,
object : CompressionListener {
override fun onProgress(percent: Float) {
//Update UI
if (percent <= 100 && percent.toInt() % 5 == 0)
runOnUiThread {
progress.text = "${percent.toLong()}%"
progressBar.progress = percent.toInt()
}
}

override fun onStart() {
time = System.currentTimeMillis()
progress.visibility = View.VISIBLE
progressBar.visibility = View.VISIBLE
originalSize.text =
"Original size: ${getFileSize(File(path).length())}"
progress.text = ""
progressBar.progress = 0
}

override fun onSuccess() {
val newSizeValue = desFile.length()

newSize.text =
"Size after compression: ${getFileSize(newSizeValue)}"

time = System.currentTimeMillis() - time
timeTaken.text =
"Duration: ${DateUtils.formatElapsedTime(time / 1000)}"

path = desFile.path

Handler().postDelayed({
progress.visibility = View.GONE
progressBar.visibility = View.GONE
}, 50)
}

override fun onFailure(failureMessage: String) {
progress.text = failureMessage
Log.wtf("failureMessage", failureMessage)
}

override fun onCancelled() {
Log.wtf("TAG", "compression has been cancelled")
// make UI changes, cleanup, etc
}
},
VideoQuality.MEDIUM,
isMinBitRateEnabled = false,
keepOriginalResolution = false
)
}

override fun onFailure(failureMessage: String) {
progress.text = failureMessage
Log.wtf("failureMessage", failureMessage)
}

override fun onCancelled() {
Log.wtf("TAG", "compression has been cancelled")
// make UI changes, cleanup, etc
}
},
VideoQuality.MEDIUM,
isMinBitRateEnabled = false,
keepOriginalResolution = false
)
}
}
}
}

Expand All @@ -159,12 +167,11 @@ class MainActivity : AppCompatActivity() {
) != PackageManager.PERMISSION_GRANTED
) {

if (ActivityCompat.shouldShowRequestPermissionRationale(
if (!ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
) {
} else {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
Expand All @@ -173,4 +180,70 @@ class MainActivity : AppCompatActivity() {
}
}
}

@Suppress("DEPRECATION")
private fun saveVideoFile(filePath: String?): File? {
filePath?.let {
val videoFile = File(filePath)
val videoFileName = "${System.currentTimeMillis()}_${videoFile.name}"
val folderName = Environment.DIRECTORY_MOVIES
if (Build.VERSION.SDK_INT >= 29) {

val values = ContentValues().apply {

put(
MediaStore.Images.Media.DISPLAY_NAME,
videoFileName
)
put(MediaStore.Images.Media.MIME_TYPE, "video/mp4")
put(MediaStore.Images.Media.RELATIVE_PATH, folderName)
put(MediaStore.Images.Media.IS_PENDING, 1)
}

val collection =
MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)

val fileUri = applicationContext.contentResolver.insert(collection, values)

fileUri?.let {
application.contentResolver.openFileDescriptor(fileUri, "w").use { descriptor ->
descriptor?.let {
FileOutputStream(descriptor.fileDescriptor).use { out ->
FileInputStream(videoFile).use { inputStream ->
val buf = ByteArray(4096)
while (true) {
val sz = inputStream.read(buf)
if (sz <= 0) break
out.write(buf, 0, sz)
}
}
}
}
}

values.clear()
values.put(MediaStore.Video.Media.IS_PENDING, 0)
applicationContext.contentResolver.update(fileUri, values, null, null)

return File(getMediaPath(applicationContext, fileUri))
}
} else {
val downloadsPath =
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
val desFile = File(downloadsPath, videoFileName)

if (desFile.exists())
desFile.delete()

try {
desFile.createNewFile()
} catch (e: IOException) {
e.printStackTrace()
}

return desFile
}
}
return null
}
}
Loading

0 comments on commit eb12847

Please sign in to comment.