Как запустить сервис в отдельном потоке
Имею два сервиса для уведомлений и воспроизведения аудио. Пробовал использовать IntentService, но работало не корректно и насколько я понял, startForegroundService() доступен только в android >= 8.
Также знаю, что можно использовать Thread или Handler, но не имею представления как организовать это, так как не нашел подходящих примеров.
А именно, где организовывать новый поток в самом сервисе, или в активности, или как-то по другому?
Логи для ответа
D/ViewRootImpl@36c1a31[MainActivity]: ViewPostIme pointer 0
D/ViewRootImpl@36c1a31[MainActivity]: ViewPostIme pointer 1
I/System.out: StartService
D/ViewRootImpl@36c1a31[MainActivity]: ViewPostIme pointer 0
D/ViewRootImpl@36c1a31[MainActivity]: ViewPostIme pointer 1
I/System.out: Destroy
// проверка кнопки
D/ViewRootImpl@36c1a31[MainActivity]: ViewPostIme pointer 0
D/ViewRootImpl@36c1a31[MainActivity]: ViewPostIme pointer 1
I/System.out: StartService
// запуск, далее сворачивание приложения
D/ViewRootImpl@36c1a31[MainActivity]: MSG_WINDOW_FOCUS_CHANGED 0 1
D/InputMethodManager: prepareNavigationBarInfo() DecorView@fa672d7[MainActivity]
D/InputMethodManager: getNavigationBarColor() -855310
D/InputTransport: Input channel destroyed: 'ClientS', fd=68
I/mali_egl: eglDestroySurface() in
I/mali_winsys: delete_surface() [1080x2340] return
I/mali_egl: eglDestroySurface() out
W/libEGL: EGLNativeWindowType 0x7760d9af50 disconnect failed
D/ViewRootImpl@36c1a31[MainActivity]: Relayout returned: old=(0,0,1080,2340) new=(0,0,1080,2340) req=(1080,2340)8 dur=10 res=0x5 s={false 0} ch=true
D/ViewRootImpl@36c1a31[MainActivity]: stopped(true) old=false
// в течении минуты
I/System.out: Destroy
Ответы (2 шт):
При помощи Thread вот так:
public class MyService extends Service {
private Thread myThread = new MyThread();
public MyService() {
super();
}
public int onStartCommand(Intent intent, int flags, int startId) {
// Если поток не запущен, то запустить
if (!myThread.isAlive())
myThread.start();
return ...;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
// Поток
private class MyThread extends Thread {
@Override
public void run() {
// Делаем что-то долгое и нудное/нужное
}
}
}
Решением для меня стал этот ответ - https://stackoverflow.com/questions/44425584/context-startforegroundservice-did-not-then-call-service-startforeground/46449975#46449975
Это нужно добавить в onCreate()
if (Build.VERSION.SDK_INT >= 26) {
String CHANNEL_ID = "my_channel_01";
NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT);
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("")
.setContentText("").build();
startForeground(1, notification);
}
Если у вас есть свои уведомления, то вы можете завершать это уведомление в onStartCommand() так:
stopForeground(true);
Да, это не очень красиво, но без вибрации и сигнала не заметно (пропадет через секунду). И не забудьте заменить создание уведомлений в вашем сервисе на
startForeground(123, notification);
Без этого работать на версиях >= api 26 не будет. Но возможно есть и другой способ.