diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 4862c91..8fb5800 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -32,15 +32,13 @@ - - + - + + - - - + - { - "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" + +}]]> diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 74cb2b6..27c7204 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -4,6 +4,7 @@ + + \ 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 index 58a68e2..1841619 100644 --- a/app/src/main/java/com/example/assignment02/AuthorityFragment.kt +++ b/app/src/main/java/com/example/assignment02/AuthorityFragment.kt @@ -55,12 +55,13 @@ class AuthorityFragment : Fragment() { } private fun requestPermission() { - if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + requestPermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE) + } else if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.FOREGROUND_SERVICE) != PackageManager.PERMISSION_GRANTED) { + requestPermissionLauncher.launch(Manifest.permission.FOREGROUND_SERVICE) + } else { // 권한이 이미 있음 openFragment() - } else { - // 권한이 없으면 권한 요청 - requestPermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE) } } diff --git a/app/src/main/java/com/example/assignment02/ListFragment.kt b/app/src/main/java/com/example/assignment02/ListFragment.kt index 657fdf1..ea54202 100644 --- a/app/src/main/java/com/example/assignment02/ListFragment.kt +++ b/app/src/main/java/com/example/assignment02/ListFragment.kt @@ -1,27 +1,35 @@ package com.example.assignment02 import android.Manifest +import android.annotation.SuppressLint import android.content.ContentResolver +import android.content.Context import android.content.Intent import android.content.pm.PackageManager -import android.net.Uri +import android.content.res.ColorStateList +import android.graphics.Color +import android.os.BatteryManager 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.LinearLayout import android.widget.TextView import androidx.core.content.ContextCompat +import androidx.core.graphics.ColorUtils 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 + private lateinit var name: TextView + private lateinit var time: TextView + private lateinit var energy: LinearLayout companion object { fun newInstance(): ListFragment { @@ -29,29 +37,47 @@ class ListFragment : Fragment() { } } + @SuppressLint("MissingInflatedId") override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val view = inflater.inflate(R.layout.fragment_list, container, false) + name = view.findViewById(R.id.name) + time = view.findViewById(R.id.time) + energy = view.findViewById(R.id.energe) + + // 배터리에 따라 배경색 변경하기! + val battery = getBatteryData(requireContext()) // 0~100(%) + energy.backgroundTintList = ColorStateList.valueOf(ColorUtils.blendARGB(Color.parseColor("#00B0FF"), Color.parseColor("#FFFFFF"), battery / 100f)) + val recycler_list: RecyclerView = view.findViewById(R.id.recycler_list) recycler_list.layoutManager = LinearLayoutManager(requireContext()) - adapter = Adapter(data) + adapter = Adapter(data, name, time) recycler_list.adapter = adapter - if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED + if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ) { - // 권한이 있음 -> 음악 파일 추가 - getMusicFilesData() - } else { - // 권한이 없음 openFragment() } + else if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.FOREGROUND_SERVICE) != PackageManager.PERMISSION_GRANTED + ) { + openFragment() + } + else { + // 권한이 있음 + getMusicFilesData() + } return view } + fun getBatteryData(context: Context): Int { + val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager + return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) + } + fun getMusicFilesData() { val contentResolver: ContentResolver = requireContext().contentResolver val uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI @@ -71,9 +97,7 @@ class ListFragment : Fragment() { 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) + val item = Item(it.getString(titleIndex) ?: "Unknown Title", it.getString(artistIndex) ?: "Unknown Artist", it.getLong(durationIndex) ?: 0, it.getString(dataIndex) ?: "") data.add(item) } adapter.notifyDataSetChanged() @@ -91,7 +115,7 @@ class ListFragment : Fragment() { .commit() } - class Adapter(private val data: MutableList) : RecyclerView.Adapter() { + class Adapter(private val data: MutableList, private var name_view:TextView, private var time_view:TextView) : RecyclerView.Adapter() { class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val title: TextView = itemView.findViewById(R.id.title) @@ -111,11 +135,19 @@ class ListFragment : Fragment() { val m = (item.duration/60000).toString() val s = (item.duration/1000 %60).toString() holder.duration.text = "$m:$s" + + holder.itemView.setOnClickListener { + name_view.text = item.title + time_view.text = holder.duration.text + val intent = Intent(holder.itemView.context, PlayMusic::class.java).apply { + putExtra("uri", item.uri) + } + ContextCompat.startForegroundService(holder.itemView.context, intent) + } } override fun getItemCount(): Int = data.size } - data class Item(val title: String, val artist: String, val duration: Long) - + data class Item(val title: String, val artist: String, val duration: Long, val uri: String) } diff --git a/app/src/main/java/com/example/assignment02/MainActivity.kt b/app/src/main/java/com/example/assignment02/MainActivity.kt index 6ffe442..ab89355 100644 --- a/app/src/main/java/com/example/assignment02/MainActivity.kt +++ b/app/src/main/java/com/example/assignment02/MainActivity.kt @@ -29,4 +29,8 @@ class MainActivity : AppCompatActivity() { .replace(R.id.fragment_container, fragment) .commit() } + override fun onBackPressed() { + super.onBackPressed() + finish() + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/assignment02/PlayMusic.kt b/app/src/main/java/com/example/assignment02/PlayMusic.kt new file mode 100644 index 0000000..222db4f --- /dev/null +++ b/app/src/main/java/com/example/assignment02/PlayMusic.kt @@ -0,0 +1,77 @@ +package com.example.assignment02 + +import android.app.Notification +import android.app.NotificationChannel +import android.app.NotificationManager +import android.app.PendingIntent +import android.app.Service +import android.content.Intent +import android.media.MediaPlayer +import android.os.Build +import android.os.IBinder +import androidx.core.app.NotificationCompat +import android.net.Uri +import android.util.Log + +class PlayMusic : Service() { + + private var mediaPlayer: MediaPlayer? = null + private val channel1 = "channel1" + + override fun onCreate() { + super.onCreate() + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val channel = NotificationChannel( + channel1, + "music", + NotificationManager.IMPORTANCE_LOW + ) + val notificationManager = getSystemService(NotificationManager::class.java) + notificationManager.createNotificationChannel(channel) + } + + val intent = Intent(this, MainActivity::class.java) + val pending_intent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE) + + // 알림 생성 + val notification: Notification = NotificationCompat.Builder(this, channel1) + .setContentTitle("음악 재생 중...") + .setContentText("백그라운드에서 음악이 재생되고 있습니다.") + .setSmallIcon(androidx.core.R.drawable.ic_call_answer) + .setContentIntent(pending_intent) + .setAutoCancel(true) + .build() + + startForeground(1, notification) + } + + override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { + val uri_string = intent.getStringExtra("uri") + Log.d("PlayMusic", "URI: $uri_string") + uri_string?.let { + val uri = Uri.parse(it) + musicPlay(uri) + } + return START_STICKY + } + + private fun musicPlay(uri: Uri) { + mediaPlayer = MediaPlayer().apply { + setDataSource(applicationContext, uri) + setOnPreparedListener { + it.start() + } + prepareAsync() + } + } + + override fun onBind(intent: Intent?): IBinder? { + return null + } + + override fun onDestroy() { + super.onDestroy() + mediaPlayer?.release() + } +} \ 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 index 999bfca..1e4ceb3 100644 --- a/app/src/main/res/layout/fragment_list.xml +++ b/app/src/main/res/layout/fragment_list.xml @@ -10,6 +10,45 @@ + android:layout_height="wrap_content" + android:layout_weight="1" > + + + + + + + + + + + + + + \ No newline at end of file