[안드로이드 백그라운드서비스] RemoteServiceException이 발생하는 이유는 무엇이며 나는 해결책을 찾고 싶다.android.app.ActivityThread$H.handleMessage
백그라운드 서비스의 경우 구글 안드로이드 운영체제가 새롭게 나올때 마다 처리방법이 달라졌다. 특히 오레오 버전부터 확 달라졌고, 그 때 부터 앱 사용자들로부터 RemoteServiceException오류가 대거 발생하기 시작했다. 해겨할 수 있는 방법이 없을까?? 나와 같은 오류를 경험한 개발자들이 많다. 하지만 그 누구도 해결책을 모르는 것일까? 아무리 구글링해도 좋은 해결책을 찾지 못했다.
첫번째 오류
가장 흔하게 몇 년 간 나를 괴롭히며 발생한 오류로 Bad notification for startForeground 오류
Fatal Exception: android.app.RemoteServiceException: Bad notification for startForeground
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2228)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:246)
at android.app.ActivityThread.main(ActivityThread.java:8443)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:596)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
두번째 오류
첫번째 오류와 마찬가지로 몇 년간 나를 괴롭힌 Context.startForegroundService() did not then call Service.startForeground() 오류
Fatal Exception: android.app.RemoteServiceException:
Context.startForegroundService() did not then call Service.startForeground():
ServiceRecord{206579e u0 com.test/.BGMService}
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1970)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7386)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:980)
세번째 오류
가장 최근에 새롭게 발생된 오류이다. 대부분 중국 폰에서 문제가 발생한다.
Fatal Exception: android.app.RemoteServiceException:
Bad notification(tag=null, id=7324)
posted from package com.test, crashing app(uid=10345, pid=20049):
Couldn't inflate contentViewsjava.lang.NullPointerException:
Attempt to invoke virtual method
'android.app.Notification$MessagingStyle
android.app.Notification$MessagingStyle.setConversationType(int)' on a null object reference
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2047)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:236)
at android.app.ActivityThread.main(ActivityThread.java:7876)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:656)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:967)
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
Intent intent = new Intent(MainActivity.this, BGMService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent);
} else {
startService(intent);
}
public class BGMService extends Service {
@Override
public void onCreate() {
super.onCreate();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//G_NOTIFICATION_ID = (int) (System.currentTimeMillis()%10000);
displayNotification(getApplicationContext(), 0, 0, 0);
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
displayNotification(getApplicationContext(), 0, 0, 0);
}
this.regisiterReceiver();
return Service.START_STICKY;
}
public void displayNotification(Context context, int level, double temperrature, double volt) {
try {
SharedPreferences sp = context.getSharedPreferences(MY_PM_PREF, Activity.MODE_PRIVATE);
myNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
//디자인 설정
getChooseDesignForStatusBar(sp, context);
//노티영역 클릭시 이동할 activity 설정
Intent newIntent = new Intent(context, MainActivity.class);
newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); //Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP //FLAG_ACTIVITY_BROUGHT_TO_FRONT
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, newIntent, PendingIntent.FLAG_UPDATE_CURRENT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//ULog.d("FROCS", "========================= G_NOTIFICATION_ID : " + G_NOTIFICATION_ID);
//int NOTIFICATION_ID = 2020;
String CHANNEL_ID = "channel_bar_2020"; //여기 수정시 NotiActivity.class에서도 변경해줘야한다.
NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
context.getResources().getString(R.string.content_txt_43),
NotificationManager.IMPORTANCE_LOW);//.IMPORTANCE_HIGH);//IMPORTANCE_LOW);
channel.setDescription(context.getResources().getString(R.string.cont_44)); // 노티 하단에 정보로 제공된다.
//channel.setAllowBubbles(false);
// channel.enableLights(true);
// channel.setLightColor(Color.RED);
channel.setShowBadge(false); //추가 : notification의 setContentTitle 안보이게 처리하기
// channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
// 잠금화면 알림 설정 (VISIBILITY)
//
// VISIBILITY_SECRET : 잠금화면 알림을 사용하지 않음
// VISIBILITY_PRIVATE : 잠금화면 알림은 표시되나, 내용은 표시되지 않음
// VISIBILITY_PUBLIC : 전체 내용을 잠금화면에 표시
//channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);
Notification notification = new androidx.core.app.NotificationCompat.Builder(this, CHANNEL_ID)
//.setContentTitle("") //자동표기됨
.setContentTitle(context.getResources().getString(R.string.content_txt_45)) //추가
.setAutoCancel(false)
//.setWhen(System.currentTimeMillis())
.setShowWhen(false)
//.setLargeIcon(null)
.setSmallIcon(getPngImage(level))
.setContentIntent(pendingIntent)
.setContent(remoteViews)
.build();
notification.flags |= Notification.FLAG_NO_CLEAR; // 지우기 버튼 눌렀을때 지워지지 않게
startForeground(G_NOTIFICATION_ID, notification);
}else {
Notification notification = new Notification.Builder(context)
.setAutoCancel(false)
//.setTicker(context.getResources().getString(R.string.info_contents_txt_5))
// .setContentTitle("My notification")
.setWhen(System.currentTimeMillis())
.setSmallIcon(getPngImage(level))
.setContentIntent(pendingIntent)
//.setPriority(Notification.PRIORITY_MAX) 상단위치값인듯,, 제일 앞으로 오게하기
.setContent(remoteViews)
.build();
notification.flags |= Notification.FLAG_NO_CLEAR; // 지우기 버튼 눌렀을때 지워지지 않게
myNotificationManager.notify(NOTI_ENABLE, notification);
}
}catch(Exception e){
//Toast.makeText(getApplicationContext(), R.string.content_txt_100, Toast.LENGTH_LONG).show();
}
}
}
백그라운드 서비스 관련 구글문서
백그라운드 실행제한 : developer.android.com/about/versions/oreo/background
developer.android.com/reference/android/app/Service#startForeground(int,%20android.app.Notification)
도움이 되려나?
proandroiddev.com/pitfalls-of-a-foreground-service-lifecycle-59f014c6a125
stackoverflow.com/questions/20857120/what-is-the-proper-way-to-stop-a-service-running-as-foreground
나에게 해결책을 달라!!!!4달라!!!