diff --git a/.idea/gradle.xml b/.idea/gradle.xml index a2d7c21..a0de2a1 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -7,6 +7,7 @@ + diff --git a/app/build.gradle b/app/build.gradle index bca158c..a7c7034 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,7 +8,7 @@ android { defaultConfig { applicationId "com.example.myapplication" - minSdk 21 + minSdk 24 targetSdk 32 versionCode 1 versionName "1.0" @@ -35,8 +35,7 @@ android { } dependencies { - - implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.core:core-ktx:1.8.0' implementation 'androidx.appcompat:appcompat:1.5.1' implementation 'com.google.android.material:material:1.7.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' @@ -44,7 +43,8 @@ dependencies { implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1' implementation 'androidx.navigation:navigation-fragment-ktx:2.5.3' implementation 'androidx.navigation:navigation-ui-ktx:2.5.3' + implementation 'com.arthenica:ffmpeg-kit-full:5.1.LTS' testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.3' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + androidTestImplementation 'androidx.test.ext:junit:1.1.4' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ba47723..bac30e0 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,6 +3,9 @@ xmlns:tools="http://schemas.android.com/tools" package="com.example.myapplication"> + + + { + val intent = Intent() + .setType("*/*") + .setAction(Intent.ACTION_GET_CONTENT) + .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + .addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION) + .addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) + + resultLauncher.launch(intent) + + Toast.makeText(applicationContext, "Files", Toast.LENGTH_LONG).show() + + return true + } + R.id.addYoutube ->{ + Toast.makeText(applicationContext, "Youtube downloading is currently not available", Toast.LENGTH_LONG).show() + return true + } + else -> super.onOptionsItemSelected(item) + } + } + + //grabs output from pressing files, used for grabbing URI + @SuppressLint("NotifyDataSetChanged") // Needed because of custom adapter + private var resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + if (result.resultCode == RESULT_OK) { + + // There are no request codes + val data: Uri? = result.data?.data + + val inUri = FFmpegKitConfig.getSafParameterForRead(this, data) + + val cursor = contentResolver.query(data!!, null, null, null, null) + + cursor?.moveToFirst() + + val fileDate = Date(System.currentTimeMillis()) + val fileName = cursor?.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME)) + + val item = CompressingItem(fileName!!, 0.0, fileDate) + + val outputFile = File(this.getExternalFilesDir(null), "converted_$fileName") + + compressingItems.add(item) + + val handler = Handler(Looper.getMainLooper()) + + + val command = "-i $inUri -c:v mpeg4 ${outputFile.absolutePath} -y" + val session = FFmpegKit.executeAsync(command) { + compressingItems.remove(item) + + handler.post { + Toast.makeText(this, "Finished converting $fileName", Toast.LENGTH_SHORT).show() + adapter.notifyDataSetChanged() + } + } + + + Log.i("Tag", Arrays.deepToString(session.arguments)) + Log.i("Tag", session.output) + + + + + + + adapter.notifyDataSetChanged() + } + } + + companion object { + val compressingItems: MutableList = mutableListOf() + + val adapter = CompressingAdapter(compressingItems) + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/ui/compressing/CompressingAdapter.kt b/app/src/main/java/com/example/myapplication/ui/compressing/CompressingAdapter.kt new file mode 100644 index 0000000..343ce7b --- /dev/null +++ b/app/src/main/java/com/example/myapplication/ui/compressing/CompressingAdapter.kt @@ -0,0 +1,34 @@ +package com.example.myapplication.ui.compressing + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ProgressBar +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.example.myapplication.R + +class CompressingAdapter(private val mCompressingItems: MutableList): RecyclerView.Adapter() { + inner class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) { + val filename: TextView = itemView.findViewById(R.id.compressing_filename) + val date: TextView = itemView.findViewById(R.id.compressing_date) + val progress: ProgressBar = itemView.findViewById(R.id.compressing_progress) + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val compressingItemView = LayoutInflater.from(parent.context).inflate(R.layout.item_compressing, parent, false) + return ViewHolder(compressingItemView) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val compressingItem: CompressingItem = mCompressingItems[position] + holder.filename.text = compressingItem.filename + holder.date.text = compressingItem.date.toString() + holder.progress.progress = compressingItem.progress.toInt() + + } + + override fun getItemCount(): Int { + return mCompressingItems.size + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/ui/compressing/CompressingFragment.kt b/app/src/main/java/com/example/myapplication/ui/compressing/CompressingFragment.kt index 4c99a79..30b2c95 100644 --- a/app/src/main/java/com/example/myapplication/ui/compressing/CompressingFragment.kt +++ b/app/src/main/java/com/example/myapplication/ui/compressing/CompressingFragment.kt @@ -4,35 +4,38 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.TextView import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.example.myapplication.MainActivity +import com.example.myapplication.MainActivity.Companion.compressingItems +import com.example.myapplication.R import com.example.myapplication.databinding.FragmentCompressingBinding class CompressingFragment : Fragment() { private var _binding: FragmentCompressingBinding? = null + + // This property is only valid between onCreateView and // onDestroyView. private val binding get() = _binding!! - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - val homeViewModel = - ViewModelProvider(this).get(CompressingViewModel::class.java) + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + ViewModelProvider(this)[CompressingViewModel::class.java] _binding = FragmentCompressingBinding.inflate(inflater, container, false) - val root: View = binding.root - val textView: TextView = binding.textCompressing - homeViewModel.text.observe(viewLifecycleOwner) { - textView.text = it - } - return root + + val compressingRecycler = binding.root.findViewById(R.id.compressing_recycler_view) as? RecyclerView + compressingRecycler?.adapter = MainActivity.adapter + compressingRecycler?.layoutManager = LinearLayoutManager(binding.root.context) + + return binding.root + + } override fun onDestroyView() { diff --git a/app/src/main/java/com/example/myapplication/ui/compressing/CompressingItem.kt b/app/src/main/java/com/example/myapplication/ui/compressing/CompressingItem.kt new file mode 100644 index 0000000..df3ab72 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/ui/compressing/CompressingItem.kt @@ -0,0 +1,5 @@ +package com.example.myapplication.ui.compressing + +import java.util.Date + +data class CompressingItem(val filename: String, val progress: Double, val date: Date) \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/ui/settings/SettingsFragment.kt b/app/src/main/java/com/example/myapplication/ui/settings/SettingsFragment.kt index 92669d7..5e2b11b 100644 --- a/app/src/main/java/com/example/myapplication/ui/settings/SettingsFragment.kt +++ b/app/src/main/java/com/example/myapplication/ui/settings/SettingsFragment.kt @@ -1,9 +1,12 @@ package com.example.myapplication.ui.settings import android.os.Bundle +import android.text.Editable +import android.text.TextWatcher import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.Toast import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import com.example.myapplication.databinding.FragmentSettingsBinding @@ -18,16 +21,73 @@ class SettingsFragment : Fragment() { private val binding get() = _binding!! override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? ): View { - val homeViewModel = - ViewModelProvider(this)[SettingsViewModel::class.java] + val homeViewModel = ViewModelProvider(this)[SettingsViewModel::class.java] _binding = FragmentSettingsBinding.inflate(inflater, container, false) val root: View = binding.root + + + + //sets the textbox visibility on startup + binding.settingCustomSizeVideoText.visibility = View.INVISIBLE + + + //updates size when size selection changes + binding.settingRadioGroup.setOnCheckedChangeListener{ group,checkedID -> + + if(checkedID == binding.settingDefaultSizeVideo.id){ + homeViewModel.size.value = 8.0 + }else if(checkedID == binding.settingBigSizeVideo.id){ + homeViewModel.size.value = 50.0 + }else if(checkedID == binding.settingHugeSize.id){ + homeViewModel.size.value = 500.0 + }else{ + try{ + homeViewModel.size.value = binding.settingCustomSizeVideoText.text.toString().toDouble() + }catch (e: NumberFormatException){ + homeViewModel.size.value = 0.0 + } + } + + Toast.makeText(root.context,"" + homeViewModel.size.value,Toast.LENGTH_SHORT).show() + + } + + //updates size when the custom value changes + binding.settingCustomSizeVideoText.addTextChangedListener ( object: TextWatcher { + + override fun afterTextChanged(s: Editable) {} + + override fun beforeTextChanged(s: CharSequence, start: Int, + count: Int, after: Int) { + } + + override fun onTextChanged(s: CharSequence, start: Int, + before: Int, count: Int) { + try{ + homeViewModel.size.value = s.toString().toDouble() + }catch (e: NumberFormatException){ + homeViewModel.size.value = 0.0 + } + Toast.makeText(root.context,"" + homeViewModel.size.value,Toast.LENGTH_SHORT).show() + } + } + ) + + //listens for changes in the custom radiobutton and hides or shows the textbox + binding.settingCustomSizeVideo.setOnCheckedChangeListener{ _, isChecked -> + if (isChecked){ + binding.settingCustomSizeVideoText.visibility = View.VISIBLE + }else{ + binding.settingCustomSizeVideoText.visibility = View.INVISIBLE + } + } + // val textView: TextView = binding.textSettings // homeViewModel.text.observe(viewLifecycleOwner) { // textView.text = it diff --git a/app/src/main/java/com/example/myapplication/ui/settings/SettingsViewModel.kt b/app/src/main/java/com/example/myapplication/ui/settings/SettingsViewModel.kt index a41f14e..f681f6c 100644 --- a/app/src/main/java/com/example/myapplication/ui/settings/SettingsViewModel.kt +++ b/app/src/main/java/com/example/myapplication/ui/settings/SettingsViewModel.kt @@ -10,4 +10,10 @@ class SettingsViewModel : ViewModel() { value = "This is settings Fragment" } val text: LiveData = _text + + //size of the file, grab this for use + private val _size = MutableLiveData().apply { + value = 8.0 + } + val size: MutableLiveData = _size } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_compressing.xml b/app/src/main/res/layout/fragment_compressing.xml index 2c7bf96..115f498 100644 --- a/app/src/main/res/layout/fragment_compressing.xml +++ b/app/src/main/res/layout/fragment_compressing.xml @@ -1,22 +1,18 @@ - - - - + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml index 75bfcd5..6930a24 100644 --- a/app/src/main/res/layout/fragment_settings.xml +++ b/app/src/main/res/layout/fragment_settings.xml @@ -10,6 +10,7 @@ android:layout_height="match_parent"> @@ -23,6 +24,7 @@ android:id="@+id/setting_default_size_video" android:layout_width="match_parent" android:layout_height="wrap_content" + android:checked="true" android:text="@string/settings_default_size" /> + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/action_bar_menu.xml b/app/src/main/res/menu/action_bar_menu.xml index 07536d2..ffd2f6c 100644 --- a/app/src/main/res/menu/action_bar_menu.xml +++ b/app/src/main/res/menu/action_bar_menu.xml @@ -6,5 +6,15 @@ android:id="@+id/add" android:title="Add" android:icon="@drawable/ic_add" - app:showAsAction="ifRoom" /> + app:showAsAction="ifRoom" > + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 00aae77..98c3fb5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -10,4 +10,6 @@ 500mb Custom Enter Size in MB + Files + Youtube \ No newline at end of file