diff --git a/.gradle/config.properties b/.gradle/config.properties
new file mode 100644
index 0000000..76e9d26
--- /dev/null
+++ b/.gradle/config.properties
@@ -0,0 +1,2 @@
+#Tue Nov 26 00:44:34 KST 2024
+java.home=C\:\\Program Files\\Android\\Android Studio1\\jbr
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..99b49d3
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+assignment02
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..4862c91
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,226 @@
+
+
+
+
+
+
+
+
+
+ @style/Theme.Assignment02
+
+
+
+
+ @style/Theme.Assignment02
+
+
+
+
+ @style/Theme.Assignment02
+
+
+
+
+ @style/Theme.Assignment02
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ "keyToString": {
+ "RunOnceActivity.OpenProjectViewOnStart": "true",
+ "RunOnceActivity.ShowReadmeOnStart": "true",
+ "RunOnceActivity.cidr.known.project.marker": "true",
+ "cf.first.check.clang-format": "false",
+ "cidr.known.project.marker": "true",
+ "last_directory_selection": "C:/Users/Public/assignment02/app/src/main/java",
+ "last_opened_file_path": "C:/Users/Public/assignment02",
+ "settings.editor.selected.configurable": "AndroidSdkUpdater"
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1731406527910
+
+
+ 1731406527910
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 166076e..25059fe 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -5,7 +5,7 @@ plugins {
android {
namespace = "com.example.assignment02"
- compileSdk = 34
+ compileSdk = 35
defaultConfig {
applicationId = "com.example.assignment02"
@@ -36,11 +36,11 @@ android {
}
dependencies {
- implementation("androidx.activity:activity-ktx:1.7.0")
- implementation("androidx.core:core-ktx:1.13.1")
+
+ implementation("androidx.core:core-ktx:1.15.0")
implementation("androidx.appcompat:appcompat:1.7.0")
implementation("com.google.android.material:material:1.12.0")
- implementation("androidx.constraintlayout:constraintlayout:2.1.4")
+ implementation("androidx.constraintlayout:constraintlayout:2.2.0")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.2.1")
androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1")
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c9ef4a9..74cb2b6 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,6 +2,9 @@
+
+
+
-
\ No newline at end of file
diff --git a/app/src/main/java/com/example/assignment02/AuthorityFragment.kt b/app/src/main/java/com/example/assignment02/AuthorityFragment.kt
new file mode 100644
index 0000000..58a68e2
--- /dev/null
+++ b/app/src/main/java/com/example/assignment02/AuthorityFragment.kt
@@ -0,0 +1,72 @@
+package com.example.assignment02
+
+import android.Manifest
+import android.content.Context
+import android.content.pm.PackageManager
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.activity.result.ActivityResultLauncher
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.core.content.ContextCompat
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentTransaction
+
+class AuthorityFragment : Fragment() {
+
+ private lateinit var requestPermissionLauncher: ActivityResultLauncher
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+
+ requestPermissionLauncher = registerForActivityResult(
+ ActivityResultContracts.RequestPermission()
+ ) { isGranted: Boolean ->
+ if (isGranted) {
+ openFragment()
+ }
+ }
+
+ requestPermission()
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ val view = inflater.inflate(R.layout.fragment_authority, container, false)
+ val authorityText = view.findViewById(R.id.authority_text)
+
+ authorityText.setOnClickListener {
+ requestPermission()
+ }
+
+ return view
+ }
+
+ private fun openFragment() {
+ val fragmentList = ListFragment.newInstance()
+ parentFragmentManager.beginTransaction()
+ .replace(R.id.fragment_container, fragmentList)
+ .addToBackStack(null)
+ .commit()
+ }
+
+ private fun requestPermission() {
+ if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
+ // 권한이 이미 있음
+ openFragment()
+ } else {
+ // 권한이 없으면 권한 요청
+ requestPermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
+ }
+ }
+
+ companion object {
+ fun newInstance(): AuthorityFragment {
+ return AuthorityFragment()
+ }
+ }
+}
diff --git a/app/src/main/java/com/example/assignment02/ListFragment.kt b/app/src/main/java/com/example/assignment02/ListFragment.kt
new file mode 100644
index 0000000..657fdf1
--- /dev/null
+++ b/app/src/main/java/com/example/assignment02/ListFragment.kt
@@ -0,0 +1,121 @@
+package com.example.assignment02
+
+import android.Manifest
+import android.content.ContentResolver
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.net.Uri
+import android.os.Bundle
+import android.provider.MediaStore
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.core.content.ContextCompat
+import androidx.fragment.app.Fragment
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import java.io.File
+
+class ListFragment : Fragment() {
+
+ private val data = mutableListOf- ()
+ private lateinit var adapter: Adapter
+
+ companion object {
+ fun newInstance(): ListFragment {
+ return ListFragment()
+ }
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ val view = inflater.inflate(R.layout.fragment_list, container, false)
+
+ val recycler_list: RecyclerView = view.findViewById(R.id.recycler_list)
+ recycler_list.layoutManager = LinearLayoutManager(requireContext())
+ adapter = Adapter(data)
+ recycler_list.adapter = adapter
+
+ if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
+ ) {
+ // 권한이 있음 -> 음악 파일 추가
+ getMusicFilesData()
+ } else {
+ // 권한이 없음
+ openFragment()
+ }
+
+ return view
+ }
+
+ fun getMusicFilesData() {
+ val contentResolver: ContentResolver = requireContext().contentResolver
+ val uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
+ val projection = arrayOf(
+ MediaStore.Audio.Media.TITLE,
+ MediaStore.Audio.Media.ARTIST,
+ MediaStore.Audio.Media.DURATION,
+ MediaStore.Audio.Media.DATA
+ )
+
+ val cursor = contentResolver.query(uri, projection, null, null, null)
+
+ cursor?.let {
+ val titleIndex = it.getColumnIndex(MediaStore.Audio.Media.TITLE)
+ val artistIndex = it.getColumnIndex(MediaStore.Audio.Media.ARTIST)
+ val durationIndex = it.getColumnIndex(MediaStore.Audio.Media.DURATION)
+ val dataIndex = it.getColumnIndex(MediaStore.Audio.Media.DATA)
+
+ while (it.moveToNext()) {
+ Log.d("File Path", "음악 파일 경로: ${it.getString(dataIndex)}")
+
+ val item = Item(it.getString(titleIndex) ?: "Unknown Title", it.getString(artistIndex) ?: "Unknown Artist", it.getLong(durationIndex) ?: 0)
+ data.add(item)
+ }
+ adapter.notifyDataSetChanged()
+ it.close()
+ } ?: run {
+ Log.e("MediaStore", "오디오 파일을 찾을 수 없습니다.")
+ }
+ }
+
+ fun openFragment() {
+ val fragment_authority = AuthorityFragment.newInstance()
+ parentFragmentManager.beginTransaction()
+ .replace(R.id.fragment_container, fragment_authority)
+ .addToBackStack(null)
+ .commit()
+ }
+
+ class Adapter(private val data: MutableList
- ) : RecyclerView.Adapter() {
+
+ class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ val title: TextView = itemView.findViewById(R.id.title)
+ val artist: TextView = itemView.findViewById(R.id.artist)
+ val duration: TextView = itemView.findViewById(R.id.duration)
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val view = LayoutInflater.from(parent.context).inflate(R.layout.fragment_list_item, parent, false)
+ return ViewHolder(view)
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ val item = data[position]
+ holder.title.text = item.title
+ holder.artist.text = item.artist
+ val m = (item.duration/60000).toString()
+ val s = (item.duration/1000 %60).toString()
+ holder.duration.text = "$m:$s"
+ }
+
+ override fun getItemCount(): Int = data.size
+ }
+
+ data class Item(val title: String, val artist: String, val duration: Long)
+
+}
diff --git a/app/src/main/java/com/example/assignment02/MainActivity.kt b/app/src/main/java/com/example/assignment02/MainActivity.kt
index acbfa04..6ffe442 100644
--- a/app/src/main/java/com/example/assignment02/MainActivity.kt
+++ b/app/src/main/java/com/example/assignment02/MainActivity.kt
@@ -1,42 +1,32 @@
package com.example.assignment02
-import android.app.Activity
-import android.content.Intent
+import android.Manifest
+import android.content.pm.PackageManager
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
-import android.widget.TextView
-import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
+import androidx.core.content.ContentProviderCompat.requireContext
+import androidx.core.content.ContextCompat
+import androidx.fragment.app.Fragment
class MainActivity : AppCompatActivity() {
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
- val number_text: TextView = findViewById(R.id.number_text)
- val count_btn: TextView = findViewById(R.id.count_btn)
- val toast_btn: TextView = findViewById(R.id.toast_btn)
- val random_btn: TextView = findViewById(R.id.random_btn)
- val intent = Intent(this, RandomActivity::class.java)
- val resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
- if (result.resultCode == Activity.RESULT_OK) {
- number_text.text = result.data?.getIntExtra("random_number", 0).toString()
- Toast.makeText(this, "OK", Toast.LENGTH_SHORT).show()
- }
- else {
- Toast.makeText(this, "오류", Toast.LENGTH_SHORT).show()
- }
- }
- count_btn.setOnClickListener {
- number_text.text = (number_text.text.toString().toInt()+1).toString()
- }
- toast_btn.setOnClickListener {
- Toast.makeText(this, "숫자 : "+number_text.text, Toast.LENGTH_LONG).show()
- }
- random_btn.setOnClickListener {
- intent.putExtra("number", number_text.text.toString().toInt())
- resultLauncher.launch(intent)
+ val fragment: Fragment = if (ContextCompat.checkSelfPermission(this,
+ Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
+ // 권한이 이미 있음
+ ListFragment.newInstance()
+ } else {
+ // 권한이 없음
+ AuthorityFragment.newInstance()
}
+
+ supportFragmentManager.beginTransaction()
+ .replace(R.id.fragment_container, fragment)
+ .commit()
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/assignment02/RandomActivity.kt b/app/src/main/java/com/example/assignment02/RandomActivity.kt
deleted file mode 100644
index 22307a7..0000000
--- a/app/src/main/java/com/example/assignment02/RandomActivity.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.example.assignment02
-
-import android.content.Intent
-import android.os.Bundle
-import android.widget.TextView
-import androidx.appcompat.app.AppCompatActivity
-import kotlin.random.Random
-
-class RandomActivity : AppCompatActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_random)
- val number_text: TextView = findViewById(R.id.number_text)
- val number = intent.getIntExtra("number", 1)
- val resultIntent = Intent()
-
- if (number > 0){
- val random_number = Random.nextInt(0, number) // 0부터 99까지의 랜덤 값
- number_text.text = random_number.toString()
- resultIntent.putExtra("random_number", random_number)
- setResult(RESULT_OK, resultIntent)
- } else {
- number_text.text = number.toString()
- resultIntent.putExtra("random_number", number)
- setResult(RESULT_OK, resultIntent)
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 0fb246d..0926cd8 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -4,49 +4,11 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:padding="30dp"
tools:context=".MainActivity">
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_random.xml b/app/src/main/res/layout/fragment_authority.xml
similarity index 55%
rename from app/src/main/res/layout/activity_random.xml
rename to app/src/main/res/layout/fragment_authority.xml
index 3f6e6ae..5d456d2 100644
--- a/app/src/main/res/layout/activity_random.xml
+++ b/app/src/main/res/layout/fragment_authority.xml
@@ -5,17 +5,26 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="30dp"
- tools:context=".MainActivity">
+ tools:context=".AuthorityFragment">
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_list.xml b/app/src/main/res/layout/fragment_list.xml
new file mode 100644
index 0000000..999bfca
--- /dev/null
+++ b/app/src/main/res/layout/fragment_list.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_list_item.xml b/app/src/main/res/layout/fragment_list_item.xml
new file mode 100644
index 0000000..4398a01
--- /dev/null
+++ b/app/src/main/res/layout/fragment_list_item.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 731cd98..b849030 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,4 +1,4 @@
-#Tue Nov 12 19:15:37 KST 2024
+#Tue Nov 26 00:44:39 KST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip