blob: e24faf669874eb60dcac944ee4db1da80d70007f [file] [log] [blame]
// Copyright 2020 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package dev.cobalt.coat;
import static dev.cobalt.media.Log.TAG;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Build.VERSION;
import android.os.IBinder;
import android.os.RemoteException;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
import dev.cobalt.util.Log;
import dev.cobalt.util.UsedByNative;
/** Implementation of the MediaPlaybackService used for Background mode media playing. */
public class MediaPlaybackService extends Service {
private static final int NOTIFICATION_ID = 193266736; // CL number for uniqueness.
private static final String NOTIFICATION_CHANNEL_ID = "dev.cobalt.coat media playback service";
private static final String NOTIFICATION_CHANNEL_NAME = "Media playback service";
@Override
public void onCreate() {
if (getStarboardBridge() == null) {
Log.e(TAG, "StarboardBridge already destroyed.");
return;
}
Log.i(TAG, "Creating a Media playback foreground service.");
super.onCreate();
getStarboardBridge().onServiceStart(this);
createNotificationChannel();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Cold start - Starting the service.");
startService();
// It is better for background media playback service.
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
// Do not support binding.
return null;
}
@Override
public void onDestroy() {
if (getStarboardBridge() == null) {
Log.e(TAG, "StarboardBridge already destroyed.");
return;
}
Log.i(TAG, "Destroying the Media playback service.");
getStarboardBridge().onServiceDestroy(this);
super.onDestroy();
}
public void startService() {
try {
startForeground(NOTIFICATION_ID, buildNotification());
} catch (IllegalStateException e) {
Log.e(TAG, "Failed to start Foreground Service", e);
}
}
public void stopService() {
// Let service itself handle notification deletion.
stopForeground(true);
stopSelf();
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= 26) {
try {
createNotificationChannelInternalV26();
} catch (RemoteException e) {
Log.e(TAG, "Failed to create Notification Channel.", e);
}
}
}
@RequiresApi(26)
private void createNotificationChannelInternalV26() throws RemoteException {
NotificationManager notificationManager =
(NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel =
new NotificationChannel(
NOTIFICATION_CHANNEL_ID,
NOTIFICATION_CHANNEL_NAME,
notificationManager.IMPORTANCE_DEFAULT);
channel.setDescription("Channel for showing persistent notification");
notificationManager.createNotificationChannel(channel);
}
Notification buildNotification() {
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
.setShowWhen(false)
.setPriority(NotificationCompat.PRIORITY_MIN)
.setSmallIcon(android.R.drawable.stat_sys_warning)
.setContentTitle("Media playback service")
.setContentText("Media playback service is running");
if (VERSION.SDK_INT >= 26) {
builder.setChannelId(NOTIFICATION_CHANNEL_ID);
}
return builder.build();
}
@UsedByNative
protected StarboardBridge getStarboardBridge() {
if (getApplication() == null) {
Log.e(TAG, "Application already destroyed.");
return null;
}
return ((StarboardBridge.HostApplication) getApplication()).getStarboardBridge();
}
}