diff --git a/app/app/src/main/AndroidManifest.xml b/app/app/src/main/AndroidManifest.xml index 32e9374..d26a8c8 100644 --- a/app/app/src/main/AndroidManifest.xml +++ b/app/app/src/main/AndroidManifest.xml @@ -1,8 +1,14 @@ + xmlns:tools="http://schemas.android.com/tools"> + + + + + android:theme="@style/Theme.Sibal"> - - - + + + @@ -30,9 +38,10 @@ + android:exported="true"> + @@ -42,14 +51,25 @@ android:exported="true"> + + + + + + + \ No newline at end of file diff --git a/app/app/src/main/java/com/example/sibal/CallEndedActivity.kt b/app/app/src/main/java/com/example/sibal/CallEndedActivity.kt index 9651102..e8ca1d7 100644 --- a/app/app/src/main/java/com/example/sibal/CallEndedActivity.kt +++ b/app/app/src/main/java/com/example/sibal/CallEndedActivity.kt @@ -1,20 +1,22 @@ package com.example.sibal import android.os.Bundle -import androidx.activity.enableEdgeToEdge +import android.os.Looper +import android.os.Handler +import android.util.Log import androidx.appcompat.app.AppCompatActivity -import androidx.core.view.ViewCompat -import androidx.core.view.WindowInsetsCompat +import com.example.sibal.databinding.ActivityCallEndedBinding class CallEndedActivity : AppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - enableEdgeToEdge() - setContentView(R.layout.activity_call_ended) - ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> - val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) - v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) - insets - } + Log.d("CallEndedActivity", "전화 종료 화면 실행") + val binding = ActivityCallEndedBinding.inflate(layoutInflater) + setContentView(binding.root) + + Handler(Looper.getMainLooper()).postDelayed({ + finish() + }, 2000) } } \ No newline at end of file diff --git a/app/app/src/main/java/com/example/sibal/CallInProgressActivity.kt b/app/app/src/main/java/com/example/sibal/CallInProgressActivity.kt index 5117e79..44da3c9 100644 --- a/app/app/src/main/java/com/example/sibal/CallInProgressActivity.kt +++ b/app/app/src/main/java/com/example/sibal/CallInProgressActivity.kt @@ -1,20 +1,47 @@ package com.example.sibal +import android.content.Intent +import android.content.pm.PackageManager +import android.graphics.Color import android.os.Bundle -import androidx.activity.enableEdgeToEdge +import android.telecom.TelecomManager +import android.util.Log +import android.view.MotionEvent +import android.widget.ImageView import androidx.appcompat.app.AppCompatActivity -import androidx.core.view.ViewCompat -import androidx.core.view.WindowInsetsCompat +import androidx.core.content.ContextCompat +import com.example.sibal.databinding.ActivityCallInProgressBinding class CallInProgressActivity : AppCompatActivity() { + private lateinit var telecomManager: TelecomManager + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - enableEdgeToEdge() - setContentView(R.layout.activity_call_progress) - ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> - val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) - v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) - insets + Log.d("CallInProgressActivity", "전화 수신 화면 실행") + val binding = ActivityCallInProgressBinding.inflate(layoutInflater) + setContentView(binding.root) + + val declineButton: ImageView = binding.decline2 + telecomManager = getSystemService(TELECOM_SERVICE) as TelecomManager + + declineButton.setOnTouchListener { v, event -> + when (event.action) { + MotionEvent.ACTION_DOWN -> { + (v as ImageView).setColorFilter(Color.argb(150, 0, 0, 0)) // 어두운 색 적용 + true + } + MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { + if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ANSWER_PHONE_CALLS) == PackageManager.PERMISSION_GRANTED) { + Log.d("IncomingCallActivity", "전화 종료") + telecomManager.endCall() + val intent = Intent(this, CallEndedActivity::class.java) + startActivity(intent) + finish() + } + true + } + else -> false + } } } } \ No newline at end of file diff --git a/app/app/src/main/java/com/example/sibal/IncomingCallActivity.kt b/app/app/src/main/java/com/example/sibal/IncomingCallActivity.kt index 138b2d8..b6a0f69 100644 --- a/app/app/src/main/java/com/example/sibal/IncomingCallActivity.kt +++ b/app/app/src/main/java/com/example/sibal/IncomingCallActivity.kt @@ -1,22 +1,107 @@ package com.example.sibal +import android.animation.AnimatorSet +import android.animation.ObjectAnimator import android.content.Intent +import android.content.pm.PackageManager +import android.content.res.Resources import android.os.Bundle -import android.os.Handler +import android.telecom.TelecomManager import android.util.Log +import android.view.MotionEvent +import android.view.View import android.widget.ImageView -import android.widget.TextView import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat import com.example.sibal.databinding.ActivityIncomingCallBinding class IncomingCallActivity : AppCompatActivity() { - - private lateinit var binding: ActivityIncomingCallBinding + private var parentWidth: Int = 0 + private lateinit var telecomManager: TelecomManager override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - Log.d("IncomingCallActivity", "덮어 쓰기 화면 실행") - binding = ActivityIncomingCallBinding.inflate(layoutInflater) + Log.d("IncomingCallActivity", "전화가 걸려왔을 때 화면 실행") + val binding = ActivityIncomingCallBinding.inflate(layoutInflater) setContentView(binding.root) + + val acceptButton = binding.accept + val declineButton = binding.decline + + setupButtonDrag(acceptButton, true) + setupButtonDrag(declineButton, false) + + parentWidth = Resources.getSystem().displayMetrics.widthPixels + telecomManager = getSystemService(TELECOM_SERVICE) as TelecomManager + } + + private fun setupButtonDrag(button: ImageView, isAcceptButton: Boolean) { + var dX = 0f + var initialX = 0f + + button.setOnTouchListener { view, event -> + when (event.action) { + //버튼을 눌렀을 때 + MotionEvent.ACTION_DOWN -> { + initialX = view.x //버튼의 초기 위치 저장 + dX = view.x - event.rawX //버튼 이동 거리 + + view.animate() + .scaleX(1.3f) + .scaleY(1.3f) + .setDuration(0) + .start() + true + } + + //버튼을 드래그 했을 때 + MotionEvent.ACTION_MOVE -> { + view.animate() + .x(event.rawX + dX) + .setDuration(0) + .start() + + //전화 수신 버튼을 화면의 오른쪽으로 충분히 이동 시켰을 경우 -> 전화 수신 + if (isAcceptButton && view.x > parentWidth * 0.4) { + if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ANSWER_PHONE_CALLS) == PackageManager.PERMISSION_GRANTED) { + Log.d("IncomingCallActivity", "전화 수신") + telecomManager.acceptRingingCall() + val intent = Intent(this, CallInProgressActivity::class.java) + startActivity(intent) + finish() + } + + //전화 거절 버튼을 화면의 왼쪽으로 충분히 이동 시켰을 경우 -> 전화 종료 + } else if (!isAcceptButton && view.x < parentWidth * 0.6) { + if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ANSWER_PHONE_CALLS) == PackageManager.PERMISSION_GRANTED) { + Log.d("IncomingCallActivity", "전화 종료") + telecomManager.endCall() + val intent = Intent(this, CallEndedActivity::class.java) + startActivity(intent) + finish() + } + } + true + } + + //버튼을 땟을 때 -> 버튼이 제자리로 돌아감 + MotionEvent.ACTION_UP -> { + //버튼 위치를 원래대로 되돌리는 애니메이션 + val moveBackAnim = ObjectAnimator.ofFloat(view, "x", initialX) + + //버튼 크기를 원래대로 되돌리는 애니메이션 + val scaleBackXAnim = ObjectAnimator.ofFloat(view, "scaleX", 1f) + val scaleBackYAnim = ObjectAnimator.ofFloat(view, "scaleY", 1f) + + //애니메이션 동시 실행 + val animatorSet = AnimatorSet() + animatorSet.playTogether(moveBackAnim, scaleBackXAnim, scaleBackYAnim) + animatorSet.duration - 300 + animatorSet.start() + true + } + else -> false + } + } } } diff --git a/app/app/src/main/java/com/example/sibal/MainActivity.kt b/app/app/src/main/java/com/example/sibal/MainActivity.kt index 73833ad..e8c7c5a 100644 --- a/app/app/src/main/java/com/example/sibal/MainActivity.kt +++ b/app/app/src/main/java/com/example/sibal/MainActivity.kt @@ -1,7 +1,10 @@ package com.example.sibal import android.Manifest +import android.Manifest.permission.ANSWER_PHONE_CALLS import android.app.role.RoleManager +import android.content.Context.ROLE_SERVICE +import android.content.Context.TELECOM_SERVICE import android.content.Intent import android.content.pm.PackageManager import android.net.Uri @@ -15,12 +18,18 @@ import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat +import androidx.core.content.ContextCompat.getSystemService class MainActivity : AppCompatActivity() { + val permissions = arrayOf( + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.ANSWER_PHONE_CALLS, + Manifest.permission.CALL_PHONE + ) + override fun onCreate(savedInstancestate: Bundle?) { super.onCreate(savedInstancestate) Log.d("메인 액티비티", "메인 액티비티 실행") - //퍼미션 런처 생성 val permissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean -> @@ -33,7 +42,9 @@ class MainActivity : AppCompatActivity() { } } //퍼미션 런처 실행 - permissionLauncher.launch("android.permission.READ_PHONE_STATE") + for(permission in permissions) { + permissionLauncher.launch(permission) + } val telecomManager = getSystemService(TELECOM_SERVICE) as TelecomManager val roleManager = getSystemService(ROLE_SERVICE) as RoleManager diff --git a/app/app/src/main/java/com/example/sibal/MyInCallService.kt b/app/app/src/main/java/com/example/sibal/MyInCallService.kt index 3aceb43..3e473f8 100644 --- a/app/app/src/main/java/com/example/sibal/MyInCallService.kt +++ b/app/app/src/main/java/com/example/sibal/MyInCallService.kt @@ -1,12 +1,8 @@ package com.example.sibal -import android.app.Service import android.content.Intent -import android.net.wifi.rtt.CivicLocationKeys.STATE -import android.os.IBinder import android.telecom.Call import android.telecom.InCallService -import android.util.Log class MyInCallService : InCallService() { diff --git a/app/app/src/main/res/drawable/accept.png b/app/app/src/main/res/drawable/accept.png new file mode 100644 index 0000000..d7cf6cb Binary files /dev/null and b/app/app/src/main/res/drawable/accept.png differ diff --git a/app/app/src/main/res/drawable/decline.png b/app/app/src/main/res/drawable/decline.png new file mode 100644 index 0000000..4d9f2ae Binary files /dev/null and b/app/app/src/main/res/drawable/decline.png differ diff --git a/app/app/src/main/res/drawable/logo.png b/app/app/src/main/res/drawable/logo.png new file mode 100644 index 0000000..71cea0a Binary files /dev/null and b/app/app/src/main/res/drawable/logo.png differ diff --git a/app/app/src/main/res/drawable/logo_black.png b/app/app/src/main/res/drawable/logo_black.png new file mode 100644 index 0000000..f094d32 Binary files /dev/null and b/app/app/src/main/res/drawable/logo_black.png differ diff --git a/app/app/src/main/res/drawable/microphone_on.png b/app/app/src/main/res/drawable/microphone_on.png new file mode 100644 index 0000000..2c7ea43 Binary files /dev/null and b/app/app/src/main/res/drawable/microphone_on.png differ diff --git a/app/app/src/main/res/drawable/rounded_rectangle1.xml b/app/app/src/main/res/drawable/rounded_rectangle1.xml new file mode 100644 index 0000000..485126b --- /dev/null +++ b/app/app/src/main/res/drawable/rounded_rectangle1.xml @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/app/app/src/main/res/drawable/rounded_rectangle2.xml b/app/app/src/main/res/drawable/rounded_rectangle2.xml new file mode 100644 index 0000000..8e833aa --- /dev/null +++ b/app/app/src/main/res/drawable/rounded_rectangle2.xml @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/app/app/src/main/res/drawable/speaker_off.png b/app/app/src/main/res/drawable/speaker_off.png new file mode 100644 index 0000000..cd06da4 Binary files /dev/null and b/app/app/src/main/res/drawable/speaker_off.png differ diff --git a/app/app/src/main/res/layout/activity_call_ended.xml b/app/app/src/main/res/layout/activity_call_ended.xml index d80ed7c..e268d8c 100644 --- a/app/app/src/main/res/layout/activity_call_ended.xml +++ b/app/app/src/main/res/layout/activity_call_ended.xml @@ -1,85 +1,87 @@ - + android:background="#000000" > - + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0.5" /> + + - - - - - - - - + android:layout_marginTop="80dp" + android:text="복지봇" + android:textColor="#FFFF00" + android:textSize="40sp" + android:textStyle="bold" + app:layout_constraintStart_toEndOf="@+id/logoYellow" + app:layout_constraintTop_toBottomOf="@+id/telNumber" /> - + android:layout_marginTop="40dp" + android:text=" 상담 종료" + android:textColor="#FFFFFF" + android:textSize="32sp" + android:textStyle="bold" + app:layout_constraintTop_toBottomOf="@+id/name" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0.5" /> - + android:textColor="#FFFFFF" + android:textSize="32sp" + android:textStyle="bold" + app:layout_constraintTop_toBottomOf="@+id/message1" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0.5" /> - - + android:layout_marginTop="30dp" + android:gravity="center" + android:text="상담하느라 수고하셨습니다. \n 곧 상담사가 연락을 드릴 예정이니 \n 조금만 기다려주세요." + android:textColor="#FFFFFF" + android:textSize="24sp" + android:textStyle="bold" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0.5" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/time" /> + \ No newline at end of file diff --git a/app/app/src/main/res/layout/activity_call_in_progress.xml b/app/app/src/main/res/layout/activity_call_in_progress.xml new file mode 100644 index 0000000..d1ef9a9 --- /dev/null +++ b/app/app/src/main/res/layout/activity_call_in_progress.xml @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/app/src/main/res/layout/activity_incoming_call.xml b/app/app/src/main/res/layout/activity_incoming_call.xml index b7b50f2..c266e05 100644 --- a/app/app/src/main/res/layout/activity_incoming_call.xml +++ b/app/app/src/main/res/layout/activity_incoming_call.xml @@ -1,84 +1,91 @@ - + android:background="#000000" + tools:context=".IncomingCallActivity"> + android:textStyle="bold" + app:layout_constraintBottom_toTopOf="@+id/name" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0.5" /> + android:textStyle="bold" + app:layout_constraintTop_toBottomOf="@+id/telNumber" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0.5"/> + android:id="@+id/logo" + android:layout_width="265dp" + android:layout_height="287dp" + android:layout_marginTop="10dp" + app:layout_constraintTop_toBottomOf="@+id/name" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0.5" + app:srcCompat="@drawable/logo" /> + android:text="상담을 원하시면 \n 전화를 받아주세요" + android:textColor="#FFFFFF" + android:textSize="32sp" + android:textStyle="bold" + app:layout_constraintTop_toBottomOf="@+id/logo" + app:layout_constraintBottom_toTopOf="@+id/accept" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0.5" /> - - - - - - - + - - - + +