Android 8.1로 업그레이드한 후 startForground 실패
전화기를 8.1 Developer Preview(개발자 미리 보기)로 업그레이드한 후 백그라운드 서비스가 더 이상 제대로 시작되지 않습니다.
장기적으로 운영되는 서비스에서 저는 다음을 구현했습니다.startForeground
생성 시 호출되는 진행 중인 알림을 시작하는 메서드입니다.
@TargetApi(Build.VERSION_CODES.O)
private fun startForeground() {
// Safe call, handled by compat lib.
val notificationBuilder = NotificationCompat.Builder(this, DEFAULT_CHANNEL_ID)
val notification = notificationBuilder.setOngoing(true)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.build()
startForeground(101, notification)
}
오류 메시지:
11-28 11:47:53.349 24704-24704/$PACKAGE_NAMEE/AndroidRuntime: FATAL EXCEPTION: main
Process: $PACKAGE_NAME, PID: 24704
android.app.RemoteServiceException: Bad notification for startForeground: java.lang.RuntimeException: invalid channel for service notification: Notification(channel=My channel pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x42 color=0x00000000 vis=PRIVATE)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1768)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
invalid channel for service notification
내인 분나예전채널의명히▁the널채▁apparently▁my▁old전예.DEFAULT_CHANNEL_ID
더 이상 API 27에 적합하지 않습니다.적절한 채널은 무엇입니까?
한동안 다른 솔루션을 사용한 후 안드로이드 8.1 이상에서 알림 채널을 만들어야 한다는 것을 알게 되었습니다.
private fun startForeground() {
val channelId =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotificationChannel("my_service", "My Background Service")
} else {
// If earlier version channel ID is not used
// https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context)
""
}
val notificationBuilder = NotificationCompat.Builder(this, channelId )
val notification = notificationBuilder.setOngoing(true)
.setSmallIcon(R.mipmap.ic_launcher)
.setPriority(PRIORITY_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build()
startForeground(101, notification)
}
@RequiresApi(Build.VERSION_CODES.O)
private fun createNotificationChannel(channelId: String, channelName: String): String{
val chan = NotificationChannel(channelId,
channelName, NotificationManager.IMPORTANCE_NONE)
chan.lightColor = Color.BLUE
chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
service.createNotificationChannel(chan)
return channelId
}
제가 알기로는 백그라운드 서비스는 이제 일반 알림으로 표시됩니다. 그러면 사용자는 알림 채널을 선택 취소하여 표시하지 않도록 선택할 수 있습니다.
업데이트: 또한 필요에 따라 전경 권한을 Android P:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
Java 솔루션(Android 9.0, API 28)
의 신의에서.Service
클래스, 추가할 항목:
@Override
public void onCreate(){
super.onCreate();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
startMyOwnForeground();
else
startForeground(1, new Notification());
}
private void startMyOwnForeground(){
String NOTIFICATION_CHANNEL_ID = "com.example.simpleapp";
String channelName = "My Background Service";
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_NONE);
chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
assert manager != null;
manager.createNotificationChannel(chan);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
Notification notification = notificationBuilder.setOngoing(true)
.setSmallIcon(R.drawable.icon_1)
.setContentTitle("App is running in background")
.setPriority(NotificationManager.IMPORTANCE_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build();
startForeground(2, notification);
}
업데이트: 안드로이드 9.0 PIE(API 28)
을 이권을에다니합에 합니다.AndroidManifest.xml
파일 이름:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
첫 번째 대답은 코틀린을 아는 사람들에게만 좋고, 여기서 여전히 자바를 사용하는 사람들에게는 제가 첫 번째 대답을 번역합니다.
public Notification getNotification() {
String channel;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
channel = createChannel();
else {
channel = "";
}
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, channel).setSmallIcon(android.R.drawable.ic_menu_mylocation).setContentTitle("snap map fake location");
Notification notification = mBuilder
.setPriority(PRIORITY_LOW)
.setCategory(Notification.CATEGORY_SERVICE)
.build();
return notification;
}
@NonNull
@TargetApi(26)
private synchronized String createChannel() {
NotificationManager mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
String name = "snap map fake location ";
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel mChannel = new NotificationChannel("snap map channel", name, importance);
mChannel.enableLights(true);
mChannel.setLightColor(Color.BLUE);
if (mNotificationManager != null) {
mNotificationManager.createNotificationChannel(mChannel);
} else {
stopSelf();
}
return "snap map channel";
}
Android의 경우 P는 이 권한을 포함하는 것을 잊지 마십시오.
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
Andorid 8.1에서 올바르게 작동합니다.
업데이트된 샘플(사용되지 않는 코드 없음):
public NotificationBattery(Context context) {
this.mCtx = context;
mBuilder = new NotificationCompat.Builder(context, CHANNEL_ID)
.setContentTitle(context.getString(R.string.notification_title_battery))
.setSmallIcon(R.drawable.ic_launcher)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setChannelId(CHANNEL_ID)
.setOnlyAlertOnce(true)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setWhen(System.currentTimeMillis() + 500)
.setGroup(GROUP)
.setOngoing(true);
mRemoteViews = new RemoteViews(context.getPackageName(), R.layout.notification_view_battery);
initBatteryNotificationIntent();
mBuilder.setContent(mRemoteViews);
mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (AesPrefs.getBooleanRes(R.string.SHOW_BATTERY_NOTIFICATION, true)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, context.getString(R.string.notification_title_battery),
NotificationManager.IMPORTANCE_DEFAULT);
channel.setShowBadge(false);
channel.setSound(null, null);
mNotificationManager.createNotificationChannel(channel);
}
} else {
mNotificationManager.cancel(Const.NOTIFICATION_CLIPBOARD);
}
}
이전 캡처됨(위 코드와 관련이 없는 다른 앱임):
@Override
public int onStartCommand(Intent intent, int flags, final int startId) {
Log.d(TAG, "onStartCommand");
String CHANNEL_ONE_ID = "com.kjtech.app.N1";
String CHANNEL_ONE_NAME = "Channel One";
NotificationChannel notificationChannel = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
notificationChannel = new NotificationChannel(CHANNEL_ONE_ID,
CHANNEL_ONE_NAME, IMPORTANCE_HIGH);
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.setShowBadge(true);
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.createNotificationChannel(notificationChannel);
}
Bitmap icon = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
Notification notification = new Notification.Builder(getApplicationContext())
.setChannelId(CHANNEL_ONE_ID)
.setContentTitle(getString(R.string.obd_service_notification_title))
.setContentText(getString(R.string.service_notification_content))
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(icon)
.build();
Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
notification.contentIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, 0);
startForeground(START_FOREGROUND_ID, notification);
return START_STICKY;
}
제 경우에는, 우리가 다음 사항을 명시하지 않고 알림을 게시하려고 했기 때문입니다.NotificationChannel
:
public static final String NOTIFICATION_CHANNEL_ID_SERVICE = "com.mypackage.service";
public static final String NOTIFICATION_CHANNEL_ID_TASK = "com.mypackage.download_info";
public void initChannel(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
nm.createNotificationChannel(new NotificationChannel(NOTIFICATION_CHANNEL_ID_SERVICE, "App Service", NotificationManager.IMPORTANCE_DEFAULT));
nm.createNotificationChannel(new NotificationChannel(NOTIFICATION_CHANNEL_ID_INFO, "Download Info", NotificationManager.IMPORTANCE_DEFAULT));
}
}
를 붙이기에 은 위놓가위좋는치장은기에에 있습니다.onCreate()
의법에 있는 Application
클래스, 그래서 우리는 모두를 위해 한 번만 선언하면 됩니다.
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
initChannel();
}
}
와 함께 알림을 사용할 수 있습니다.channelId
우리가 방금 지정한 것
Intent i = new Intent(this, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pi = PendingIntent.getActivity(this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID_INFO);
.setContentIntent(pi)
.setWhen(System.currentTimeMillis())
.setContentTitle("VirtualBox.exe")
.setContentText("Download completed")
.setSmallIcon(R.mipmap.ic_launcher);
그런 다음 알림을 게시하는 데 사용할 수 있습니다.
int notifId = 45;
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
nm.notify(notifId, builder.build());
포그라운드 서비스의 알림으로 사용하려는 경우:
startForeground(notifId, builder.build());
@CopsOnRoad 덕분에 그의 솔루션은 큰 도움이 되었지만 SDK 26 이상에서만 작동합니다.내 앱은 24 이상을 목표로 합니다.
Android Studio가 불만을 제기하지 않도록 하려면 알림에 직접 조건부가 필요합니다.코드가 VERSION_CODE.O에 조건부인 메서드에 있다는 것을 아는 것은 현명하지 않습니다.
@Override
public void onCreate(){
super.onCreate();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
startMyOwnForeground();
else
startForeground(1, new Notification());
}
private void startMyOwnForeground(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
String NOTIFICATION_CHANNEL_ID = "com.example.simpleapp";
String channelName = "My Background Service";
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_NONE);
chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
assert manager != null;
manager.createNotificationChannel(chan);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
Notification notification = notificationBuilder.setOngoing(true)
.setSmallIcon(AppSpecific.SMALL_ICON)
.setContentTitle("App is running in background")
.setPriority(NotificationManager.IMPORTANCE_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build();
startForeground(2, notification);
}
}
이것은 저에게 효과가 있었습니다.서비스 클래스에서 안드로이드 8.1용 알림 채널을 아래와 같이 만들었습니다.
public class Service extends Service {
public static final String NOTIFICATION_CHANNEL_ID_SERVICE = "com.package.MyService";
public static final String NOTIFICATION_CHANNEL_ID_INFO = "com.package.download_info";
@Override
public void onCreate() {
super.onCreate();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
nm.createNotificationChannel(new NotificationChannel(NOTIFICATION_CHANNEL_ID_SERVICE, "App Service", NotificationManager.IMPORTANCE_DEFAULT));
nm.createNotificationChannel(new NotificationChannel(NOTIFICATION_CHANNEL_ID_INFO, "Download Info", NotificationManager.IMPORTANCE_DEFAULT));
} else {
Notification notification = new Notification();
startForeground(1, notification);
}
}
}
참고: 알림을 만들 채널을 만듭니다.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
대안적인 답변: 화웨이 기기이고 Oreo 8 Android에 필요한 요구 사항을 구현했으며 유일한 기기 문제보다 여전히 화웨이 기기에만 문제가 있는 경우 https://dontkillmyapp.com/huawei 을 읽을 수 있습니다.
저도 같은 문제가 있었습니다.두 앱에 동일한 채널 ID와 알림 ID를 사용했을 때 문제가 발생했습니다.따라서 고유한 알림 ID와 채널 ID를 사용해 보십시오.
이것은 오래되었을 수도 있지만, 누군가가 나와 같은 상황을 겪었을 경우에 대비합니다.어떤 이유에서인지, 안드로이드 11 OnePlus Nord에서.
Notification.Builder().Build()
충돌,
NotificationCompat.Builder().Build()
잘 작동합니다.Androidx.core.app으로 마이그레이션하는 것을 고려해 보십시오.NotificationCompat.
VPN 라이브러리로 작업하는 경우 이 코드가 도움이 될 것입니다. 이 코드를 내부에 배치했습니다.onCreate(savedInstanceState: Bundle?)
NotificationChannelManager.createNotificationChannelIfNeeded(
activity,
channelName = "Chanel Name",
channelDescription = "Channel description"
)
이것이 나의 해결책입니다.
private static final int NOTIFICATION_ID = 200;
private static final String CHANNEL_ID = "myChannel";
private static final String CHANNEL_NAME = "myChannelName";
private void startForeground() {
final NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
getApplicationContext(), CHANNEL_ID);
Notification notification;
notification = mBuilder.setTicker(getString(R.string.app_name)).setWhen(0)
.setOngoing(true)
.setContentTitle(getString(R.string.app_name))
.setContentText("Send SMS gateway is running background")
.setSmallIcon(R.mipmap.ic_launcher)
.setShowWhen(true)
.build();
NotificationManager notificationManager = (NotificationManager) getApplication().getSystemService(Context.NOTIFICATION_SERVICE);
//All notifications should go through NotificationChannel on Android 26 & above
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
CHANNEL_NAME,
NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(NOTIFICATION_ID, notification);
}
도움이 되길 바랍니다 :)
언급URL : https://stackoverflow.com/questions/47531742/startforeground-fail-after-upgrade-to-android-8-1
'programing' 카테고리의 다른 글
ts1206 데코레이터는 여기서 사용할 수 없습니다. Angular 2 (0) | 2023.08.01 |
---|---|
문자열을 QString으로 변경하는 방법은 무엇입니까? (0) | 2023.08.01 |
루트 문서 아래 디렉터리에 없는 문서에 스핑크스를 연결할 수 있습니까? (0) | 2023.08.01 |
scss/css에서 파일 이름 "_" 또는 "_" 앞에 붙이는 이유는 무엇입니까? (0) | 2023.08.01 |
사용자가 C# + As에서 Active Directory 그룹에 속해 있는지 확인합니다.그물 (0) | 2023.08.01 |