타겟SDK 30 적용기 <2 : 토스트 메시지 UI를 함부로 바꾸지 말 것>
토스트 UI를 커스터마이징 한 안드로이드 앱은 쉽게 찾아보기 어렵다.
내가 본 앱 중에서 이걸 커스터마이징한 앱은 우리앱 밖에 없었다.
타겟SDK를 30으로 올리고 앱을 실행한 순간 null point exception 크래시가 났다.
이유는 간단했다. 타겟SDK 30부터는 토스트 메시지 UI를 함부로 바꿀 수 없기 때문이다.
API30에서 Toast의 setView 메소드가 Deprecated 되었다고 한다. 뷰가 없어서 처음에 토스트 메세지를 보여주려다가 null...
<API 30에서의 Toast setView 메소드 설명>
/**
* Set the view to show.
*
* @see #getView
* @deprecated Custom toast views are deprecated. Apps can create a standard text toast with the
* {@link #makeText(Context, CharSequence, int)} method, or use a
* <a href="{@docRoot}reference/com/google/android/material/snackbar/Snackbar">Snackbar</a>
* when in the foreground. Starting from Android {@link Build.VERSION_CODES#R}, apps
* targeting API level {@link Build.VERSION_CODES#R} or higher that are in the background
* will not have custom toast views displayed.
*/
@Deprecated
public void setView(View view) {
mNextView = view;
}
대부분 안드로이드 앱들은 아래 코드로 토스트를 띄운다.
Toast.makeText(context, text, mToastLength).show();
내가 생각하는 이 코드의 단점은 중복호출할 경우 바로바로 텍스트 교체가 안된다는 점이다.
그래서 이걸 싱글톤으로 ToastManager를 따로 구현해서 쓰고있었는데... 토스트 캔슬이 참 좋았다.
그래서 아래와 같이 직접 구현한 show메소드에서 setView타는 부분만 SDK버전 분기를 쳐서 해결했다.
public void show(Context context, CharSequence text) {
try {
/* SDK 30(R) 부터는 커스텀 토스트 뷰가 deprecated 되어 사용하면 안됨 */
if (mToast != null) {
mToast.cancel(); // Toast 메시지 연속해서 보여주는 경우 기존 토스트 취소
}
mToast = new Toast(context);
mToast.setDuration(mToastLength);
mToast.setGravity(mGravity, 0, 0);
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.R){
mToast.setView(getView(context));
}
mToast.setText(text);
mToast.show();
} catch (Exception e){
Toast.makeText(context, text, mToastLength).show();
}
}
setView 메소드가 Deprecated 된 이유를 생각해보자면 두가지 일 것이다.
1. 안드로이드 12부터는 토스트가 시멘트색 → 흰색으로 바뀌어서 그렇게 한 것 같다.
2. 구글에서 스낵바 쓰기를 권장함. 그러나 토스트를 대체할 정도인지는 잘 모르겠다.