ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Android Notification 예제 ( Oreo, androidx 적용 )
    Android/개념 및 예제 2019. 8. 13. 15:02





    오레오(Oreo API 26) 이상부터는 채널을 추가해야 노티피케이션을 사용할 수 있다는 것을 알게되어 포스트를 수정합니다.

    안드로이드 폰에서 사용하는 운영체제 버전에 따라 실행결과가 다릅니다. 




    1. 노티피케이션 동작 설명


    2. 전체 소스코드


    3. 관련 포스트


    4. 참고



    2015.02.19 - 최초작성

    2016.10.22

    2019.08.13 - 오레오를 위한 코드  추가


    1. 노티피케이션 동작 설명


    실행시키면 노티피케이션을 발생시키는 버튼을 보여줍니다.  

    버튼을 터치할 때마다 변수 count 값을 증가시켜주도록 했습니다. 

    최종적으로 노티피케이션에 의해 전달되는 값은 마지막에 전달한 값이 되는 걸 확인하기 위해서 입니다. 


    3번 터치한 후 결과를 보겠습니다. 





    노티피케이션 우선순위가 충분히 높다면 아래처럼  헤드업(heads-up) 알림이 보입니다. 이때 터치해도 됩니다. 

    우선순위가 높지 않으면 헤드업 알림이 보이지 않고 다음 단계에 보이는 스크린샷처럼 아이콘만 보여줍니다. 


    참고로 에뮬레이터에서도 헤드업 알림이 보이지 않습니다.





    왼쪽 위에 작은 아이콘으로 알림이 도착한 것을 알려줍니다.





    상태바를 아래로 드래그하면 자세한 알림 정보를 볼 수 있습니다.  

    알림을 터치해주면 다른 액티비티로 넘어가도록 했습니다. 이 때  변수 count 값을 전달합니다. 





    새로운 액티비티가 실행되면서 앞에서 버튼을 터치한 횟수를 보여줍니다.  

    앞에서 3번 터치해서 3이 보입니다. 

    변수 count의 마지막 값만 사용자가 볼 수 있다는 것을 알 수 있습니다. 

    즉 알림이 여러개 와도 마지막에 온 알림에 해당하는 정보만 볼 수 있도록 구현되어 있습니다. 






    앱 정보에서 다음처럼 등록한 알림 채널을 볼 수 있고.. 사용자가 수정도 가능합니다.


    앱 알림을 선택합니다.





    노티페케이션 채널이(오타가 났네요..) 코드에서 추가한 채널입니다.

    해당 채널을 터치하면.





    채널에서 변경가능한 값들을 보여줍니다. 





    2. 전체 소스코드 


    API 29와 androidx를 사용하여 작성하였습니다. 



    build.gradle

    노티피케이션을 사용하기 위해 필요한 패키지를 설치해줍니다.


    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
        implementation 'androidx.appcompat:appcompat:1.1.0-rc01'
        implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
        testImplementation 'junit:junit:4.12'
        androidTestImplementation 'androidx.test:runner:1.2.0'
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
        implementation "androidx.core:core:1.0.2"
    }



    AndroidManifest.xml


    노트피케이션 결과를 보여줄 액티미티를 매니페스트에 추가해줍니다.


    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.tistory.webnautes.notificationexample">

        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />

                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>

            <activity
                android:name=".ResultActivity"
                android:parentActivityName=".MainActivity" >
            </activity>
        </application>

    </manifest>



    activity_main.xml


    노티피케이션을 발생시킬 버튼이 추가되어 있습니다.


    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <Button
            android:text="노티피케이션 발생시키기"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            android:layout_marginTop="20dp"
            android:id="@+id/button" />

    </androidx.constraintlayout.widget.ConstraintLayout>



    result_main.xml


    노티피케이션 동작 결과를 보여줄 버튼이 추가되어 있습니다. 

    필요시 이 버튼에 다른 동작을 추가하면 좋을 듯합니다. 


    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <Button
            android:text=""
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            android:layout_marginTop="20dp"
            android:id="@+id/textView" />

    </androidx.constraintlayout.widget.ConstraintLayout>




    MainActivity.java


    노티피케이션이 구현된 자바코드입니다.


    package com.tistory.webnautes.notificationexample;

    import androidx.appcompat.app.AppCompatActivity;
    import androidx.core.app.NotificationCompat;

    import android.app.NotificationChannel;
    import android.app.NotificationManager;
    import android.app.PendingIntent;
    import android.content.Context;
    import android.content.Intent;
    import android.graphics.BitmapFactory;
    import android.os.Build;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;

    public class MainActivity extends AppCompatActivity {

        public static final String NOTIFICATION_CHANNEL_ID = "10001";
        private int count = 0;


        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            Button button = (Button) findViewById(R.id.button);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View arg0) {

                    // 버튼을 누를때마다 count 를 증가시며 최근에 보낸 노티피케이션만 사용자의 탭 대기중인지 테스트
                    count++;
                    NotificationSomethings();
                }
            });
        }

        public void NotificationSomethings() {


            NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);

            Intent notificationIntent = new Intent(this, ResultActivity.class);
            notificationIntent.putExtra("notificationId", count); //전달할 값
            notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK) ;
            PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent,  PendingIntent.FLAG_UPDATE_CURRENT);

            NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
                    .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_foreground)) //BitMap 이미지 요구
                    .setContentTitle("상태바 드래그시 보이는 타이틀")
                    .setContentText("상태바 드래그시 보이는 서브타이틀")
                    // 더 많은 내용이라서 일부만 보여줘야 하는 경우 아래 주석을 제거하면 setContentText에 있는 문자열 대신 아래 문자열을 보여줌
                    //.setStyle(new NotificationCompat.BigTextStyle().bigText("더 많은 내용을 보여줘야 하는 경우..."))
                    .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                    .setContentIntent(pendingIntent) // 사용자가 노티피케이션을 탭시 ResultActivity로 이동하도록 설정
                    .setAutoCancel(true);

            //OREO API 26 이상에서는 채널 필요
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

                builder.setSmallIcon(R.drawable.ic_launcher_foreground); //mipmap 사용시 Oreo 이상에서 시스템 UI 에러남
                CharSequence channelName  = "노티페케이션 채널";
                String description = "오레오 이상을 위한 것임";
                int importance = NotificationManager.IMPORTANCE_HIGH;

                NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName , importance);
                channel.setDescription(description);

                // 노티피케이션 채널을 시스템에 등록
                assert notificationManager != null;
                notificationManager.createNotificationChannel(channel);

            }else builder.setSmallIcon(R.mipmap.ic_launcher); // Oreo 이하에서 mipmap 사용하지 않으면 Couldn't create icon: StatusBarIcon 에러남

            assert notificationManager != null;
            notificationManager.notify(1234, builder.build()); // 고유숫자로 노티피케이션 동작시킴

        }

    }



    ResultActivity.java


    노티피케이션 결과 전달 받은 숫자를 보여주는 역활을 합니다. 


    package com.tistory.webnautes.notificationexample;

    import android.app.NotificationManager;
    import android.content.Context;
    import android.os.Bundle;
    import android.widget.TextView;

    import androidx.annotation.Nullable;
    import androidx.appcompat.app.AppCompatActivity;

    public class ResultActivity extends AppCompatActivity {

        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            setContentView(R.layout.result_main);


            String text = "전달 받은 값은";
            int id = 0;

            Bundle extras = getIntent().getExtras();
            if (extras == null) {
                text = "값을 전달 받는데 문제 발생";
            }
            else
                id = extras.getInt("notificationId");

            TextView textView = (TextView) findViewById(R.id.textView);
            textView.setText(text + " " + id);

            NotificationManager notificationManager =  (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

            //노티피케이션 제거
            notificationManager.cancel(id);
        }
    }





    3. 관련 포스트


    안드로이드 예제 - 알람 보여주기 위해 화면을 켜는 방법(PowerManager.WakeLock)

    https://webnautes.tistory.com/1368



    화면이 꺼진 상태에서 알람 메시지를 보여주기 위해 화면을 켜는 방법을 소개합니다.



    4. 참고

    [1] https://developer.android.com/training/notify-user/build-notification?hl=ko


    [2] https://stackoverflow.com/questions/43093260/notification-not-showing-in-oreo


    [3] https://stackoverflow.com/questions/47368187/android-oreo-notification-crashes-system-ui




    포스트 작성시에는 문제 없었지만 이후 문제가 생길 수 있습니다.
    댓글로 알려주시면 빠른 시일내에 답변을 드리겠습니다.

    여러분의 응원으로 좋은 컨텐츠가 만들어집니다. 지금 본 내용이 도움이 되었다면 후원 또는 유튜브 구독 부탁드립니다. 감사합니다 : )

    유튜브 구 독 하 기
    후 원 하 기


    댓글 11

    • ㅎㅎ 2016.08.23 18:23


      감사합니다!!! 참고 잘 하고 가요!!!

    • kun 2016.11.03 14:39


      안녕하세요!! 항상 블로그 보면서 공부 잘 하고 있습니다..!! 정말 감사합니다 ㅜㅜ그런데 혹시 노티피케이션의 내용을 그대로 읽어오는 예제는 없는지 궁금합니다..

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2016.11.03 19:16 신고


        Intent를 이용하여 값 전달하는 부분을 찾아 수정해보세요..
        참고 : http://egloos.zum.com/hiiq/v/1877208

        MainActivity의 notificationIntent.putExtra("notificationId", 9999);부분을 원하는 문자열을 넘겨주는 것으로 변경하고

        NotificationSomething 에서 Bundle extras = getIntent().getExtras();부분을 문자열을 넘겨 받는 것으로 변경하면 됩니다.



      • kun 2016.11.03 19:43


        답변 감사합니다!! 그런데 그 값을 넣어주라고 하셨는데, 만약에 카카오톡이나 페이스북 같은 핸드폰 내부에서 알림이 뜬다면 그 값을 어떻게 읽어오는지 그걸 여쭈어 보고 싶습니다..!!

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2016.11.03 19:55 신고


        저도 해본게 아니라 찾아보니 아래 블로그의 글이 나오네요..

        http://highway-to-j.blogspot.kr/2015/11/no3-notification-listener-caturing.html

      • kun 2016.11.03 20:24


        답변 정말 감사합니다!!ㅜㅜ 덕분에 도움 많이 되었습니다!! 정말감사합니다!!

    • ㅇㅇ 2016.11.18 15:44


      안녕하세요. 검색하다 들어왔는데 다른곳은 다 꼬여서 뭔지도 몰랐는데 친절하게 알려주셔서 드디어 성공했어요 정말 감사합니다 ㅠㅠㅠㅠㅠㅠ

    • ㄳㄳ 2017.01.25 17:08


      잘보고 갑니다 23버전이라 어캐하나 찾았는데 좋은 어플 있었네요. ㄳㄳ

    • 감사합니다 2019.11.10 20:40


      감사합니다. 구글링해도 말이 너무어려워서 한참 헤맸는데 덕분에 막혔던 부분 완성했어요.
      2년전게시글인데 지금보다니...ㅜㅜ

Designed by Tistory.