Mein Vordergrunddienst zeigt keine Benachrichtigung an, wenn er auf Android Oreo funktioniert.Eine Benachrichtigung des Vordergrunddienstes wird auf Android 8 nicht angezeigt. +
Es funktioniert perfekt auf Android-Versionen von 15 bis 25 Wenn ich targetSdkVersion
von 26
zu 25
dieses Problem verschwindet tun. Aber diese Lösung scheint nicht gut zu sein.
Ich bereitete test project mit diesem Problem vor.
Was soll ich tun, um es auf Android Oreo mit targetSdkVersion 26
zu beheben?
Mein Vordergrund Service, SoundService.java (full source):
public class SoundService extends Service implements MediaPlayer.OnErrorListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnBufferingUpdateListener {
private final static String TAG = SoundService.class.getSimpleName();
static private int mStateService = MusicConstants.STATE_SERVICE.NOT_INIT;
private final Uri mUriRadioDefault = Uri.parse("https://nfw.ria.ru/flv/audio.aspx?ID=75651129&type=mp3");
private final Object mLock = new Object();
private final Handler mHandler = new Handler();
private MediaPlayer mPlayer;
private Uri mUriRadio;
private NotificationManager mNotificationManager;
private WifiManager.WifiLock mWiFiLock;
private PowerManager.WakeLock mWakeLock;
private Handler mTimerUpdateHandler = new Handler();
private Runnable mTimerUpdateRunnable = new Runnable() {
@Override
public void run() {
mNotificationManager.notify(MusicConstants.NOTIFICATION_ID_FOREGROUND_SERVICE, prepareNotification());
mTimerUpdateHandler.postDelayed(this, MusicConstants.DELAY_UPDATE_NOTIFICATION_FOREGROUND_SERVICE);
}
};
private Runnable mDelayedShutdown = new Runnable() {
public void run() {
unlockWiFi();
unlockCPU();
stopForeground(true);
stopSelf();
}
};
public SoundService() {
}
public static int getState() {
return mStateService;
}
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
mStateService = MusicConstants.STATE_SERVICE.NOT_INIT;
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mUriRadio = mUriRadioDefault;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent == null) {
stopForeground(true);
stopSelf();
return START_NOT_STICKY;
}
switch (intent.getAction()) {
case MusicConstants.ACTION.START_ACTION:
mStateService = MusicConstants.STATE_SERVICE.PREPARE;
startForeground(MusicConstants.NOTIFICATION_ID_FOREGROUND_SERVICE, prepareNotification());
destroyPlayer();
initPlayer();
play();
break;
case MusicConstants.ACTION.PAUSE_ACTION:
mStateService = MusicConstants.STATE_SERVICE.PAUSE;
mNotificationManager.notify(MusicConstants.NOTIFICATION_ID_FOREGROUND_SERVICE, prepareNotification());
destroyPlayer();
mHandler.postDelayed(mDelayedShutdown, MusicConstants.DELAY_SHUTDOWN_FOREGROUND_SERVICE);
break;
case MusicConstants.ACTION.PLAY_ACTION:
mStateService = MusicConstants.STATE_SERVICE.PREPARE;
mNotificationManager.notify(MusicConstants.NOTIFICATION_ID_FOREGROUND_SERVICE, prepareNotification());
destroyPlayer();
initPlayer();
play();
break;
case MusicConstants.ACTION.STOP_ACTION:
Log.i(TAG, "Received Stop Intent");
destroyPlayer();
stopForeground(true);
stopSelf();
break;
default:
stopForeground(true);
stopSelf();
}
return START_NOT_STICKY;
}
@Override
public void onDestroy() {
destroyPlayer();
mStateService = MusicConstants.STATE_SERVICE.NOT_INIT;
try {
mTimerUpdateHandler.removeCallbacksAndMessages(null);
} catch (Exception e) {
e.printStackTrace();
}
super.onDestroy();
}
private void destroyPlayer() {
if (mPlayer != null) {
try {
mPlayer.reset();
mPlayer.release();
} catch (Exception e) {
e.printStackTrace();
} finally {
mPlayer = null;
}
}
unlockWiFi();
unlockCPU();
}
public boolean onError(MediaPlayer mp, int what, int extra) {
destroyPlayer();
mHandler.postDelayed(mDelayedShutdown, MusicConstants.DELAY_SHUTDOWN_FOREGROUND_SERVICE);
mNotificationManager.notify(MusicConstants.NOTIFICATION_ID_FOREGROUND_SERVICE, prepareNotification());
mStateService = MusicConstants.STATE_SERVICE.PAUSE;
return false;
}
...
//Part of code was skipped
...
private Notification prepareNotification() {
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.setAction(MusicConstants.ACTION.MAIN_ACTION);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
} else {
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Intent lPauseIntent = new Intent(this, SoundService.class);
lPauseIntent.setAction(MusicConstants.ACTION.PAUSE_ACTION);
PendingIntent lPendingPauseIntent = PendingIntent.getService(this, 0, lPauseIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Intent playIntent = new Intent(this, SoundService.class);
playIntent.setAction(MusicConstants.ACTION.PLAY_ACTION);
PendingIntent lPendingPlayIntent = PendingIntent.getService(this, 0, playIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Intent lStopIntent = new Intent(this, SoundService.class);
lStopIntent.setAction(MusicConstants.ACTION.STOP_ACTION);
PendingIntent lPendingStopIntent = PendingIntent.getService(this, 0, lStopIntent, PendingIntent.FLAG_UPDATE_CURRENT);
RemoteViews lRemoteViews = new RemoteViews(getPackageName(), R.layout.radio_notification);
lRemoteViews.setOnClickPendingIntent(R.id.ui_notification_close_button, lPendingStopIntent);
switch (mStateService) {
case MusicConstants.STATE_SERVICE.PAUSE:
lRemoteViews.setViewVisibility(R.id.ui_notification_progress_bar, View.INVISIBLE);
lRemoteViews.setOnClickPendingIntent(R.id.ui_notification_player_button, lPendingPlayIntent);
lRemoteViews.setImageViewResource(R.id.ui_notification_player_button, R.drawable.ic_play_arrow_white);
break;
case MusicConstants.STATE_SERVICE.PLAY:
lRemoteViews.setViewVisibility(R.id.ui_notification_progress_bar, View.INVISIBLE);
lRemoteViews.setOnClickPendingIntent(R.id.ui_notification_player_button, lPendingPauseIntent);
lRemoteViews.setImageViewResource(R.id.ui_notification_player_button, R.drawable.ic_pause_white);
break;
case MusicConstants.STATE_SERVICE.PREPARE:
lRemoteViews.setViewVisibility(R.id.ui_notification_progress_bar, View.VISIBLE);
lRemoteViews.setOnClickPendingIntent(R.id.ui_notification_player_button, lPendingPauseIntent);
lRemoteViews.setImageViewResource(R.id.ui_notification_player_button, R.drawable.ic_pause_white);
break;
}
NotificationCompat.Builder lNotificationBuilder = new NotificationCompat.Builder(this);
lNotificationBuilder
.setContent(lRemoteViews)
.setSmallIcon(R.mipmap.ic_launcher)
.setCategory(NotificationCompat.CATEGORY_TRANSPORT)
.setOngoing(true)
.setAutoCancel(true)
.setContentIntent(pendingIntent);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
lNotificationBuilder.setVisibility(Notification.VISIBILITY_PUBLIC);
}
return lNotificationBuilder.build();
}
@Override
public void onPrepared(MediaPlayer mp) {
mStateService = MusicConstants.STATE_SERVICE.PLAY;
mNotificationManager.notify(MusicConstants.NOTIFICATION_ID_FOREGROUND_SERVICE, prepareNotification());
try {
mPlayer.setWakeMode(this, PowerManager.PARTIAL_WAKE_LOCK);
} catch (Exception e) {
e.printStackTrace();
}
mPlayer.start();
mTimerUpdateHandler.postDelayed(mTimerUpdateRunnable, 0);
}
private void lockCPU() {
...
//Part of code was skipped
...
}
private void unlockCPU() {
...
//Part of code was skipped
...
}
private void lockWiFi() {
...
//Part of code was skipped
...
}
private void unlockWiFi() {
...
//Part of code was skipped
...
}
}
Mein build.gradle:
apply plugin: 'com.android.application'
repositories {
maven { url 'https://maven.google.com' }
}
android {
compileSdkVersion 26
buildToolsVersion "26.0.1"
defaultConfig {
applicationId "com.example.foreground"
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile "com.android.support:support-compat:${project.ext.supportLibVersion}"
compile "com.android.support:support-v4:${project.ext.supportLibVersion}"
compile "com.android.support:design:${project.ext.supportLibVersion}"
compile "com.android.support:appcompat-v7:${project.ext.supportLibVersion}"
compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12'
}
Wo project.ext.supportLibVersion = '26.1.0'
Sehen Sie, wie es funktioniert auf Android API
Trotz des Erstellens eines Vordergrunddienstes macht Will **, der nicht ** einen 'NotificationChannel' definiert, den Dienst zu einem Kandidaten, der von OS in Oreo getötet werden soll? Ich habe bemerkt, dass der Vordergrund-Dienst nach einiger Zeit getötet wurde !!? – ranjjose
@ranjjose: "Wenn ich keinen NotificationChannel nehme, mache den Dienst zu einem Kandidaten, der von OS in Oreo getötet werden soll?" - Ich habe dieses Szenario nicht ausprobiert, tut mir leid. – CommonsWare
danke für die schnelle Antwort. Ich habe ein paar Tippfehler korrigiert. – ranjjose