FCM Push 알림

 

FCM은 앱의 키값을 식별하여 특정 스마트폰에 데이터를 전달할 수 있다. 앱의 고유한 키 값은 Firebase에 앱을 등록하면 생성된다. 사용자가 이 앱을 설치하고 알람설정에 동의하면 기기의 FCM token을 얻을 수 있다.

 

 

작업 프로세스

  1. Manifest 수정
    • 서비스 등록
    • 권한 설정
  1. Token 생성
    • 앱이 처음으로 실행되면 자동으로 발급된다.
      • 앱이 새 기기에서 복원 될 때, 사용자가 앱을 제거/재설치할 때, 사용자가 앱 데이터를 지울 때 토큰이 변경될 수 있다.
    • FirebaseMessagingService를 상속받아 onNewToken() 을 오버라이딩 해야한다.
      • 새 토큰이 생성될 때마다 onNewToken() 콜백이 실행된다.
    /**
     * Called if the FCM registration token is updated. This may occur if the security of
     * the previous token had been compromised. Note that this is called when the
     * FCM registration token is initially generated so this is where you would retrieve the token.
     */
    override fun onNewToken(token: String) {
        Log.d(TAG, "Refreshed token: $token")
    
        // If you want to send messages to this application instance or
        // manage this apps subscriptions on the server side, send the
        // FCM registration token to your app server.
        sendRegistrationToServer(token)
    }
  1. 현재 토큰 가져오기
    • 현재 토큰을 검색해야 하는 경우 FirebaseMessaging.getInstance().getToken()을 호출한다.
    FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task ->
        if (!task.isSuccessful) {
            Log.w(TAG, "Fetching FCM registration token failed", task.exception)
            return@OnCompleteListener
        }
    
        // Get new FCM registration token
        val token = task.result
    
        // Log and toast
        val msg = getString(R.string.msg_token_fmt, token)
        Log.d(TAG, msg)
        Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
    })
  1. 메세지 수신
    • FirebaseMessagingService를 상속받은 서비스 에서 onMessageReceived() 콜백을 오버라이딩 해야한다.
    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        // TODO(developer): Handle FCM messages here.
        // Not getting messages here? See why this may be: https://goo.gl/39bRNJ
        Log.d(TAG, "From: ${remoteMessage.from}")
    
        // Check if message contains a data payload.
        if (remoteMessage.data.isNotEmpty()) {
            Log.d(TAG, "Message data payload: ${remoteMessage.data}")
    
            if (/* Check if data needs to be processed by long running job */ true) {
                // For long-running tasks (10 seconds or more) use WorkManager.
                scheduleJob()
            } else {
                // Handle message within 10 seconds
                handleNow()
            }
        }
    
        // Check if message contains a notification payload.
        remoteMessage.notification?.let {
            Log.d(TAG, "Message Notification Body: ${it.body}")
        }
    
        // Also if you intend on generating your own notifications as a result of a received FCM
        // message, here is where that should be initiated. See sendNotification method below.
    }
    Notification를 받는 경우, Foreground/Background에 따라 다르게 동작한다.
  1. 안드로이드 알림 생성(Data를 받는 경우)
    private fun sendNotification(title: String, text: String, requestId: Int){
          
            val intent = Intent(this, CardRequestActivity::class.java).apply {
                flags = Intent.FLAG_ACTIVITY_CLEAR_TOP and Intent.FLAG_ACTIVITY_NEW_TASK
            }
            val pendingIntent = PendingIntent.getActivity(this, 0, intent, FLAG_MUTABLE)
    
            val channelId = getString(R.string.notification_channel_id)
            val channelName = getString(R.string.default_notification_channel_name)
            val defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
            val notificationBuilder = NotificationCompat.Builder(this, channelId)
                .setAutoCancel(true)
                .setSound(defaultSound)
                .setContentText(text)
                .setContentTitle(title)
                .setContentIntent(pendingIntent)
                .setSmallIcon(R.drawable.bling)
            // create notification channel
            val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            val channel = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH)
            notificationManager.createNotificationChannel(channel)
            notificationManager.notify(0, notificationBuilder.build())
        }
    }
    • PendingIntent를 생성해서 연결될 페이지를 지정하면 된다.
     

 

[Android] FCM PUSH Notification (FCM PUSH 알림
https://koharinn.tistory.com/587

Android에서 Firebase 클라우드 메시징 클라이언트 앱 설정
https://firebase.google.com/docs/cloud-messaging/android/client?hl=ko

 

 

WebView Communication

Device Token

FirebaseMessagingService 클래스의 onNewToken(String token) 메소드를 override 하여 DeviceToken값을 얻을 수 있다.

 

FirebaseMessagingService
 
 

Communication between WebView and Native

 

  • 안드로이드에서 자바스크립트 코드 실행
    • webView.evaluateJavascript(script, resultCallback) 사용
    • 예제1. 웹뷰의 배경색 변경 (1-way communication) 
    • webView.evaluateJavascript("document.body.style.background = 'blue';", null)
    • 예제2. 네이티브 쪽으로 데이터 리턴받기
      • 익명함수를 생성할 수 도 있다.
      • 반환값은 JSON value, JSON object, JSON array등으로 오기 때문에, unwrap하는 과정이 필요하다.
      webView.evaluateJavascript(
      		"(function() { return document.getElementById('toastMessage').value; })();"
      ) { returnValue ->
      		Toast.makeText(requireContext(), returnValue, Toast.LENGTH_SHORT).show()
      }
    • 그 외에, 자바스크립트 함수를 호출하거나, 파라미터로 값을 넘길 수 있다.
      webView.evaluateJavascript("getToastMessage();") { returnValue ->
          Toast.makeText(requireContext(), returnValue, Toast.LENGTH_SHORT).show()
      }
      webView.evaluateJavascript("concatenateStrings('${arg1}', '${arg2}');") { returnValue ->
          Toast.makeText(requireContext(), returnValue, Toast.LENGTH_SHORT).show()
      }

     

    Communication with WebView Using JavaScript in Android

  • 자바스크립트에서 안드로이드 메소드 호출

    In Android

    1. 자바스크립트 사용 설정
      val myWebView: WebView = findViewById(R.id.webview)
      myWebView.settings.javaScriptEnabled = true
    1. 자바스크립트 코드를 Android 코드에 결합
      • 자바스크립트 코드와 안드로이드 코드 간에 인터페이스를 만들 수 있다.
      • 자바 스크립트에서 Android 코드의 메소드를 호출 가능하게 해준다.
        • 아래 예제에서는 Toast를 띄운다.
      class WebAppInterface(private val mContext: Context) {
      		@JavascriptInterface
      		fun showToast(toast: String) {
      				Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show()
      		}
      }
      • 웹뷰에서 실행되는 자바 스크립트에 이 클래스를 결합하고, 인터페이스의 이름을 지정할 수 있다.
        • 아래 예제에서 인터페이스의 이름을 Android로 설정하였다.
      myWebView.addJavaScriptInterface(WebAppInterface(this), "Android")

    In Web

    1. 인터페이스 사용
      • 위와 같이 자바스크립트 인터페이스를 만들었다면, WebView에서 실행되는 자바스크립트를 위한 Android라는 인터페이스가 만들어진다.
      • 자바 스크립트에서 Android라는 인터페이스를 초기화할 필요 없이 WebView가 자동으로 설정해준다.
      <input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" />
      
      <script type="text/javascript">
          function showAndroidToast(toast) {
              Android.showToast(toast);
          }
      </script>
      • 버튼을 클릭하면, WebAppInterface.showToast()를 호출한다.
      • 인자에 원하는 값을 담아 전달할 수 있다.

     

    WebView에서 웹 앱 빌드 | Android 개발자 | Android Developers

     

 

Google I/O Extended 2023 Cloud Busan & Busan 에서 발표한 자료입니다. 
https://festa.io/events/3820

본 발표는 안드로이드에서 웹 컨텐츠를 사용하는 방식을 다룹니다.

목차

  1. 발표 주제 소개
    • 주제 선정 이유, 발표에서 다루는 내용을 말합니다.
  2. 안드로이드와 웹
    • 안드로이드에서 웹 컨텐츠를 어디에 사용하는지, 어떻게 사용하는지 알아봅니다.
  3. WebView
    • 안드로이드의 웹뷰에 대해 알아봅니다.
  4. New in Web on Android
    • 2023 Google I/O에서 발표된 New in Web on Android 세션을 리뷰합니다.

 

우선 저는 안드로이드를 개발하고 있지만, 통계적으로 봤을 , 모바일 보다는 쪽에 관심있는 분들이 많을 같았고, 
그래서 개발이나 개발하시는 분들 모두 들을 있는 주제로 선정하고자 했습니다.

해당 발표에서는 안드로이드에서 컨텐츠를 어떻게 사용하고어떤건 되고, 어떤건 안된다. 
뭐가 좋고 뭐가 안좋다 이런 것들을 알아보려고 합니다.

그래서 앞으로 모바일과 협업할 있을 , "? 그거 된다고 하던데요." 라고 있는 정도로 알아가셨으면 좋겠습니다.

그리고 이번 Google I/O에서 발표된 New in Web on Android 같이 리뷰 해보는 시간을 갖겠습니다. 

모바일 앱에서 웹컨텐츠를 사용하는 경우는 어떤게 있을까요?
대표적으로는 카카오톡에서 링크를 클릭했을 때가 있겠습니다. 
앱안에서 링크가 열리는 것을 있습니다.

다른 예시를 보겠습니다. 토스의 증권탭, 카카오톡 쇼핑탭, 당근의 근처 탭도 모두 웹컨텐츠를 보여주고 있습니다. 
이런 탭들은 웹인지도 모를정도로 웹컨텐츠를 활용하고 있습니다.

이렇게 네이티브 구현할 있는 화면을 굳이 웹으로 만들까요?
첫번째는 비용입니다.

비용이라 하면 
첫번째로는 개발 시간입니다. 
android, ios, web 따로 개발하지 않아도 되죠.

두번째는 인력입니다. 
개발자 명만 있어도, , android, ios 커버칠 있습니다. 
그리고 개발자가 개발자에 비해 개발자 풀이 넓어 인력을 수급하기도 쉽습니다.

세번째는 배포속도입니다. 
앱에서 배포를 한다고 하면, 앱스토어에서 업데이트하고, 사용자가 앱을 업데이트 해야 최신기능이 반영됩니다. 
앱스토어 심사 등으로 배포자체가 늦어지기도 하고, 사용자가 앱을 업데이트 안하는 경우도 존재합니다. 
웹으로 배포하면 앱을 업데이트 일이 없으니까, 시간이 단축되고, 사용자의 피로를 낮춰줄 있습니다.

두 번째 이유로, 이벤트 페이지 처럼 자주 변하는 화면은 웹로 하는게 좋습니다.

이제 앞에서 컨텐츠를 어디서, 사용하는지 알아봤습니다. 
이제 안드로이드에서 컨텐츠를 어떤 식으로 보여줄 있는지 보겠습니다.

첫번째는 그냥 외부 브라우저로 이동시키는 방식이 있습니다. 제일 간편한 방법입니다. 

번째는 크롬 커스텀 탭이 있습니다. 앱안에서 열리는 크롬 탭이라고 생각하시면 됩니다. 

그리고 번째로 웹뷰라는 컴포넌트를 사용하는 방식이 있습니다.

3가지를 비교해본 표입니다.

속도

속도는 커스텀 탭이 가장 빠릅니다. 백그라운드에서 Pre-warming을 해서 퍼포먼스를 향상 시킬 수도 있습니다. 

브라우저는 브라우저 앱을 실행하고 로드하는 과정이 필요하기 때문에 비교적 Custom Tabs 보다 느립니다. 

웹 뷰는 뷰 객체를 생성하고 초기화하는데 시간이 오래걸려 비교적 느립니다. 

브라우징 기능

일단 브라우저는 브라우징을 위해 만들어진 것이기 때문에 모든 표준을 준수합니다. 

커스텀 탭도 크롬을 사용하기 때문에 동일합니다. 그리고 크롬브라우저와 캐시와 쿠키도 공유합니다.

웹뷰의 경우 표준을 지원안하는 경우도 있고, 앱마다 쿠키를 따로 관리하기 때문에 브라우징 자체의 기능은 떨어진다고   있습니다.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    

앱과의 연결성

브라우저의 경우는 별도의 앱이 실행되는 것이므로, 페이지를 닫거나 하는 등의 컨트롤을 하기가 어렵고브라우저 사용중의 우리의 앱이 꺼질 위험도 있습니다. 

커스텀 탭의 경우 안에서 열리기 때문에 컨텍스트 스위칭이 일어나지 않고 자연스럽게 사용할 있습니다. 

뷰는 안에서 일부분만 보여준다거나 자유롭게 사용할 있습니다.

커스텀 가능여부

브라우저는 커스텀 가능한 부분이 없고, 앱으로 돌아올 데이터를 받거나 하기 어렵습니다. 

커스텀 탭은 닫기버튼이나 색깔 정도 커스텀할 있고 몇가지 상황에 대한 콜백을 처리할 수도 있습니다. 

웹뷰는 네이티브 컴포넌드들과 같이 같이 쓴다거나, 웹에서 자바스크립트를 실행한다거나, 로딩 단계에 콜백을 추가한다거나 자유롭게 사용할 있다.

보안

보안의 경우 브라우저와 커스텀 탭은 크롬등의 브라우저를 사용하기 때문에 브라우저의 보안을 따라갑니다. 세이프 브라우징을 사용하고 별도의 프로세스에서 동작하기 때문에 앱에 리소스에 접근하기 어렵고 비교적 안전하다고 있습니다. 

웹뷰의 경우는 웹에서 네이티브 코드를 실행하거나 하는 위험성이 있습니다.
그래서 검증되지 않은 사이트보다는 본인의 사이트를 보여주는데 적합합니다.

우선 안드로이드의 뷰는 최신버전 기준으로 크로미움 엔진을 사용합니다.

그리고 웹뷰를 사용할 때는 웹뷰와 웹뷰 클라이언트, 웹뷰 크롬 클라이언트 3가지 클래스를 대표적으로 사용합니다.

웹뷰는 뷰를 표시하는 객체이고, 클라이언트는 웹페이지 로딩 일어나는 콜백을 정의할 있는 클래스입니다. 

크롬 클라이언트는 웹페이지 안에서 일어나는 액션에 대한 콜백을 정의할 있습니다.

클래스들은 웹이 로드되는 순서에 따라 콜백이 호출됩니다. 

url 로드한다고 하면, 페이지가 로드 시작, 리소스 다운로드, 타이틀 받아오기, 페이지 로드 완료 로딩 순서대로 호출됩니다. 

이제 코드로 보겠습니다. 

우선 이번 발표에서는 컴포즈라는 새로운 구성방식이 아닌 기존의 xml 사용해서 설명하겠습니다. 

이렇게 xml 뷰를 선언해주고, 인스턴스를 생성해줍니다.

웹 뷰 클라이언트를 설정해주고 loadUrl 페이지를 로드해주면, 오른쪽 화면처럼 페이지가 로드됩니다. 

하지만 이상태에서는 자바스크립트가 제대로 동작하지 않기 때문에 settings 자바스크립트 eabled 속성을 true 해주어야 자바스크립트가 동작하게됩니다.

settings 통해서는 웹뷰의 캐시 모드 설정이나, 유저에이전트, 파일 접근 권한, 멀티 윈도우 허용, 허용 등의 설정을 있습니다.

앞의 예제에서는 기본 웹뷰 클라이언트를 사용했는데 웹 뷰 클라이언트를 상속받아 구현할 수도 있습니다.

이렇게 메소드들을 오버라이딩 해서 구현하면 됩니다.

이런 메소드들은 로딩단계에 대한 콜백인데, 대표적인 것들만 살펴보겠습니다.

should override url loading 웹뷰에 url 로드되기 전에 호출되는 콜백입니다. 

페이지 로딩에서는 실행되지 않고, 웹뷰 안에서 페이지를 이동할 호출됩니다. 

콜백에서 특정 url 접근을 제한한다거나 있습니다. 

onPagestarted onPageFinished처럼 페이지가 시작된 호출되는 콜백과 페이지 로딩이 끝난 호출되는 콜백이 있습니다. 

그리고 에러처리도 있습니다. 400번대 이상의 http error 발생했을 호출되는 콜백입니다.

콜백을 통해 404등의 에러페이지가 나왔을 다른 네이티브 화면을 띄운다거나 있습니다. 

SSL 연결이 실패하면 호출되는 콜백입니다.

webview 기본적으로 https 지원하므로 ssl 연결이 필수적인데, 인증된 기관에서 발행한 ssl인증서가 아니면 에러가 발생합니다.

에러가 발생했을 때는 에러를 무시하고 페이지를 로드할 수 도 있고, 오른쪽 사진처럼 인증서가 올바르지않은데 진행하겠냐는 다이얼로그를 띄울 수도 있다. 

하지만 이렇게 처리 할 시에는 스토어 등록에 문제가 생길 수 도 있다. 

외에도 리소스를 받을 , 사용자가 입력한 키에대한 콜백, 히스토리에 페이지가 추가될 등에 대한 처리를 해줄 있습니다. 

웹뷰 클라이언트와 별개로 크롬 클라이언트도 설정해줄 있습니다 .

역시 크롬클라이언트를 상속받아 구현합니다 .

웹뷰 클라이언트가 페이지 로딩에 따른 콜백이었다면 웹크롬 클라이언트는 페이지 안에서 일어나는 액션들의 콜백입니다.

여기도 대표적인 함수들을 몇개 보겠습니다. 

페이지 로딩 정도를 알려주는 콜백 함수입니다. 오른쪽 이미지처럼 프로그래스 바로 진행정도를 표시하거나 하는 등의 용도로 사용할 있습니다.

그리고 윈도우(새탭)가 열릴때나 닫힐 호출되는 콜백이 있습니다. 

다음으로 Js에서 Alert, comfirm, prompt 호출되었을 , 호출되는 콜백이 있습니다. 

여기 안에서 다이얼로그를 표시하거나, 토스트를 표시하거나, 별도의 뷰를 띄우거나 등등 사용자가 원하는대로 커스텀할 있습니다.

그리고 권한 요청이나, 콘솔메세지 출력에 대한 콜백도 있습니다. 

그리고 상에서 프로필 사진 변경이나 게시물 작성을 파일 chooser 눌렀을 호출되는 콜백이 있습니다 .

네이티브 상에서 별도의 라이브러리를 쓰거나 갤러리를 열거나 등의 액션을 있습니다.

그 외에도 위치 권한 요청에 대한 콜백이나, JsTimeout 등의 콜백이 존재합니다. 

그리고 안드로이드 네이티브에서 자바스크립트 함수를 실행 / 호출 하거나, 웹 안에서 안드로이드의 네이티브 코드를 호출하거나 하는 등의 행위를 할 수 있습니다. 

먼저 안드로이드에서 자바스크립트를 실행하는 코드를 보겠습니다. 

evaluateJavascript를 써서 자바스크립트 코드를 실행할 있습니다. 

이렇게 html 배경 색을 변경할 있습니다.

익명함수를 만들고 실행하여 반환값을 받을 수도 있습니다.

여기 예제에서는 반환값을 받아 토스트를 표시하고 있습니다.

토스트는 이런 UI 요소입니다. 

그리고 웹 페이지에 정의되어있는 자바스크립트 함수를 실행할 수도 있습니다. 

다음으로 웹에서 안드로이드 코드를 실행하는 과정을 보겠습니다.

우선 안드로이드에서 자바스크립트 인터페이스를 등록해줍니다Android라는 이름으로 인터페이스를 추가해줬습니다.

그리고 자바스크립트에서 Android.showToast 이런식으로 실행해주면 네이티브에서 함수가 호출됩니다. 

외에도 디버그 옵션을 켜서 디버깅을 한다거나 있습니다. 

마지막으로 웹뷰의 한계점은 다음과 같습니다. 

속도면에서 리소스들을 다운받고 html 받아서 웹을 그리기 때문에 네이티브보다 반응속도가 느립니다. 

 File Chooser  유튜브 풀스크린 같이 웹에서 당연하게 지원하는 것들을 기본적으로 지원하지 않습니다. 

개발자가 따로 커스텀 해줘야합니다. 

캐시, 쿠키가 앱마다 관리되기 때문에 A앱에서 네이버에 로그인 해놨는데 B앱에서는 로그인이 안되는 있는 경우가 생기기도 합니다. 

HTML5 CSS 일부 기능이 지원되지 않을 수도 있습니다. 

그리고 애드센스가 포함된 웹페이지에서 애드센스가 안보일 수도 있다고 합니다. 

이번 구글 IO 2023에서 발표되었던 new in web on android 대한 간략 소개입니다. 

기존에 웹뷰를 통해 웹에 접속하면 요청해더에 항상 x-requested-with 포함시켰다. 

웹에서 어떤 앱을 통해 들어왔는지 있었다. 

유저 프라이버시를 위해 기능을 deprecation 했다.

그리고 원래 구축해놓은 웹사이트에서 헤더에 의존성이 있을 있으므로, 특정 오리진에만 적용할 있도록 속성을 만들어 줬습니다. 

그리고 이제 웹뷰에서도 chrome origin trials 사용할 있게 되었습니다 .

이를 통해 크롬의 기능이나 실험적기능을 테스트 있습니다.

화면을 사용할 , 웹 뷰의 이미지나 텍스트를 드래그앤 드롭으로 가져올 있습니다.

Text input field 손글씨를 사용할 있습니다.

Jetpack Javascript Engine  컨텐츠를 표시하지 않고도 안에서 자바스크립트를 실행할 있게 해주는 엔진입니다. 

웹과 비지니스 로직을 공유할 간편하게 사용할 있습니다.

웹뷰 인스턴스를 생성하지 않고도 자바스크립트와 어셈블리 코드를 실행할 수 있고, 웹 뷰에 비해 적은 리소스를 사용하는 게 장점입니다.

자바스크립트 코드는 별도의 프로세스에서 실행되어 안전하고 안정적이라고 합니다. 

이제 앞에서 잠 설명했던 custom tab 관한 내용입니다. 

원래 custom tab은 full screen으로만 열렸는데 높이를 조절할 있게 되었습니다. 

오른쪽에 보이는 것처럼 유튜브에서 예시를 있습니다. 

태블릿 같은 화면에서 사용되었을 가로세로 자동으로 전환해준다고 합니다. 

세로일 떄 - Bottom Sheet 형태, 가로일 때 - Side bar 형태

그리고 Engagement를 수치적으로 측정할 수 있습니다. 

커스텀 탭안에서 얼마나 머물렀는지, 스크롤에 대한 정보들을 측정할 있습니다. 

 

끝.


 

 

 

 

 

 

 

행사를 위해 노력해주신 GDG Cloud Busan, GDG Busan 분들 그리고 스탭 분들 감사합니다. 

GDSC 활동 이후에 첫 외부활동인데 잘 마무리된 거 같아 다행입니다. 

 

PendingIntent

PendingIntent란 대기 중인 인텐트라는 뜻으로, 현재 어플리케이션이 살아있는지와 관계없이 특정 시점에 Intent를 수행할 수 있게 해주는 것이다.

다른 어플리케이션을 통해 Intent를 실행할 수 있도록 PendingIntent를 전달할 수 있다.

예시

  • Notification
    • NotificationManager에게 PendingIntent 전달
  • Widget
    • RemoteView에 ClickListener로 PendingIntent를 설정
    • AppWidgetManager가 PendingIntent를 실행
  • 특정 시점에 실행
    • AlarmManager에게 PendingIntent 전달

Android 12 부터는 PendingIntent를 만들 때 변경 가능 여부를 지정해야한다.

  • PendingIntent.FLAG_MUTABLE
  • PendingIntent.FLAG_IMMUTABLE

PendingIntent는 변경될 수 있는데, 악성 앱이 PendingIntent를 수정하여, 우리 앱의 다른 컴포넌트에 접근할 수도 있다.

Foreground Service

백그라운드에서 포그라운드 서비스를 시작할 수 없다.

앱이 백그라운드 상태에 있는 동안 포그라운드 서비스를 시작하려고 하면 ForegroundServiceStartNotAllowedException 이 발생한다.

WorkManager를 사용해야한다.

백그라운드에서 포그라운드 서비스 실행이 허용되는 경우

다음 상황에서는 앱이 백그라운드에서 실행되는 동안에도 포그라운드 서비스를 시작할 수 있습니다.

  • 앱이 활동과 같은 사용자에게 표시되는 상태에서 전환됩니다.
  • 사용자가 앱과 관련된 UI 요소에서 작업을 실행합니다. 예를 들어 대화창이나 알림위젯, 활동과 상호작용할 수 있습니다.
  • 사용자가 앱의 배터리 최적화를 사용 중지합니다. 시스템 설정에서 앱의 앱 정보 페이지로 사용자를 보내 사용자가 이 옵션을 찾도록 할 수 있습니

포그라운드 서비스 실행 제한  |  Android 12  |  Android Developers


Uploaded by N2T

+ Recent posts