android: converted Main from java to kotlin
This commit is contained in:
parent
034bcf4f44
commit
0bf77f4eb3
@ -1,338 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
// Copyright The Music Player Daemon Project
|
||||
|
||||
package org.musicpd;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.PowerManager;
|
||||
import android.os.RemoteCallbackList;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.OptIn;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.session.MediaSession;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.musicpd.data.LoggingRepository;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import dagger.hilt.android.AndroidEntryPoint;
|
||||
|
||||
@AndroidEntryPoint
|
||||
public class Main extends Service implements Runnable {
|
||||
|
||||
private static final String TAG = "Main";
|
||||
private static final String WAKELOCK_TAG = "mpd:wakelockmain";
|
||||
|
||||
private static final int MAIN_STATUS_ERROR = -1;
|
||||
private static final int MAIN_STATUS_STOPPED = 0;
|
||||
private static final int MAIN_STATUS_STARTED = 1;
|
||||
|
||||
private static final int MSG_SEND_STATUS = 0;
|
||||
|
||||
private Thread mThread = null;
|
||||
private int mStatus = MAIN_STATUS_STOPPED;
|
||||
private boolean mAbort = false;
|
||||
private String mError = null;
|
||||
private final RemoteCallbackList<IMainCallback> mCallbacks = new RemoteCallbackList<IMainCallback>();
|
||||
private final IBinder mBinder = new MainStub(this);
|
||||
private boolean mPauseOnHeadphonesDisconnect = false;
|
||||
private PowerManager.WakeLock mWakelock = null;
|
||||
|
||||
private MediaSession mMediaSession = null;
|
||||
|
||||
@Inject
|
||||
LoggingRepository logging;
|
||||
|
||||
@NotNull
|
||||
public static final String SHUTDOWN_ACTION = "org.musicpd.action.ShutdownMPD";
|
||||
|
||||
static class MainStub extends IMain.Stub {
|
||||
private Main mService;
|
||||
MainStub(Main service) {
|
||||
mService = service;
|
||||
}
|
||||
public void start() {
|
||||
mService.start();
|
||||
}
|
||||
public void stop() {
|
||||
mService.stop();
|
||||
}
|
||||
public void setPauseOnHeadphonesDisconnect(boolean enabled) {
|
||||
mService.setPauseOnHeadphonesDisconnect(enabled);
|
||||
}
|
||||
public void setWakelockEnabled(boolean enabled) {
|
||||
mService.setWakelockEnabled(enabled);
|
||||
}
|
||||
public boolean isRunning() {
|
||||
return mService.isRunning();
|
||||
}
|
||||
public void registerCallback(IMainCallback cb) {
|
||||
mService.registerCallback(cb);
|
||||
}
|
||||
public void unregisterCallback(IMainCallback cb) {
|
||||
mService.unregisterCallback(cb);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void sendMessage(int what, int arg1, int arg2, Object obj) {
|
||||
int i = mCallbacks.beginBroadcast();
|
||||
while (i > 0) {
|
||||
i--;
|
||||
final IMainCallback cb = mCallbacks.getBroadcastItem(i);
|
||||
try {
|
||||
switch (what) {
|
||||
case MSG_SEND_STATUS:
|
||||
switch (arg1) {
|
||||
case MAIN_STATUS_ERROR:
|
||||
cb.onError((String)obj);
|
||||
break;
|
||||
case MAIN_STATUS_STOPPED:
|
||||
cb.onStopped();
|
||||
break;
|
||||
case MAIN_STATUS_STARTED:
|
||||
cb.onStarted();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
mCallbacks.finishBroadcast();
|
||||
}
|
||||
|
||||
private Bridge.LogListener mLogListener = new Bridge.LogListener() {
|
||||
@Override
|
||||
public void onLog(int priority, String msg) {
|
||||
logging.addLogItem(priority, msg);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return mBinder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
if (intent != null && Objects.equals(intent.getAction(), SHUTDOWN_ACTION)) {
|
||||
stop();
|
||||
} else {
|
||||
start();
|
||||
if (intent != null && intent.getBooleanExtra("wakelock", false))
|
||||
setWakelockEnabled(true);
|
||||
}
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!Loader.loaded) {
|
||||
final String error = "Failed to load the native MPD libary.\n" +
|
||||
"Report this problem to us, and include the following information:\n" +
|
||||
"SUPPORTED_ABIS=" + String.join(", ", Build.SUPPORTED_ABIS) + "\n" +
|
||||
"PRODUCT=" + Build.PRODUCT + "\n" +
|
||||
"FINGERPRINT=" + Build.FINGERPRINT + "\n" +
|
||||
"error=" + Loader.error;
|
||||
setStatus(MAIN_STATUS_ERROR, error);
|
||||
stopSelf();
|
||||
return;
|
||||
}
|
||||
synchronized (this) {
|
||||
if (mAbort)
|
||||
return;
|
||||
setStatus(MAIN_STATUS_STARTED, null);
|
||||
}
|
||||
Bridge.run(this, mLogListener);
|
||||
setStatus(MAIN_STATUS_STOPPED, null);
|
||||
}
|
||||
|
||||
private synchronized void setStatus(int status, String error) {
|
||||
mStatus = status;
|
||||
mError = error;
|
||||
sendMessage(MSG_SEND_STATUS, mStatus, 0, mError);
|
||||
}
|
||||
|
||||
private Notification.Builder createNotificationBuilderWithChannel() {
|
||||
final NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
if (notificationManager == null)
|
||||
return null;
|
||||
|
||||
final String id = "org.musicpd";
|
||||
final String name = "MPD service";
|
||||
final int importance = 3; /* NotificationManager.IMPORTANCE_DEFAULT */
|
||||
|
||||
try {
|
||||
Class<?> ncClass = Class.forName("android.app.NotificationChannel");
|
||||
Constructor<?> ncCtor = ncClass.getConstructor(String.class, CharSequence.class, int.class);
|
||||
Object nc = ncCtor.newInstance(id, name, importance);
|
||||
|
||||
Method nmCreateNotificationChannelMethod =
|
||||
NotificationManager.class.getMethod("createNotificationChannel", ncClass);
|
||||
nmCreateNotificationChannelMethod.invoke(notificationManager, nc);
|
||||
|
||||
Constructor nbCtor = Notification.Builder.class.getConstructor(Context.class, String.class);
|
||||
return (Notification.Builder) nbCtor.newInstance(this, id);
|
||||
} catch (Exception e)
|
||||
{
|
||||
Log.e(TAG, "error creating the NotificationChannel", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(markerClass = UnstableApi.class)
|
||||
private void start() {
|
||||
if (mThread != null)
|
||||
return;
|
||||
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
|
||||
registerReceiver(new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (!mPauseOnHeadphonesDisconnect)
|
||||
return;
|
||||
if (intent.getAction() == AudioManager.ACTION_AUDIO_BECOMING_NOISY)
|
||||
pause();
|
||||
}
|
||||
}, filter);
|
||||
|
||||
final Intent mainIntent = new Intent(this, MainActivity.class);
|
||||
mainIntent.setAction("android.intent.action.MAIN");
|
||||
mainIntent.addCategory("android.intent.category.LAUNCHER");
|
||||
final PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
|
||||
mainIntent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
||||
|
||||
Notification.Builder nBuilder;
|
||||
if (Build.VERSION.SDK_INT >= 26 /* Build.VERSION_CODES.O */)
|
||||
{
|
||||
nBuilder = createNotificationBuilderWithChannel();
|
||||
if (nBuilder == null)
|
||||
return;
|
||||
}
|
||||
else
|
||||
nBuilder = new Notification.Builder(this);
|
||||
|
||||
Notification notification = nBuilder.setContentTitle(getText(R.string.notification_title_mpd_running))
|
||||
.setContentText(getText(R.string.notification_text_mpd_running))
|
||||
.setSmallIcon(R.drawable.notification_icon)
|
||||
.setContentIntent(contentIntent)
|
||||
.build();
|
||||
|
||||
mThread = new Thread(this);
|
||||
mThread.start();
|
||||
|
||||
MPDPlayer player = new MPDPlayer(Looper.getMainLooper());
|
||||
mMediaSession = new MediaSession.Builder(this, player).build();
|
||||
|
||||
startForeground(R.string.notification_title_mpd_running, notification);
|
||||
startService(new Intent(this, Main.class));
|
||||
}
|
||||
|
||||
private void stop() {
|
||||
mMediaSession.release();
|
||||
mMediaSession = null;
|
||||
if (mThread != null) {
|
||||
if (mThread.isAlive()) {
|
||||
synchronized (this) {
|
||||
if (mStatus == MAIN_STATUS_STARTED)
|
||||
Bridge.shutdown();
|
||||
else
|
||||
mAbort = true;
|
||||
}
|
||||
}
|
||||
try {
|
||||
mThread.join();
|
||||
mThread = null;
|
||||
mAbort = false;
|
||||
} catch (InterruptedException ie) {}
|
||||
}
|
||||
setWakelockEnabled(false);
|
||||
stopForeground(true);
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
private void pause() {
|
||||
if (mThread != null) {
|
||||
if (mThread.isAlive()) {
|
||||
synchronized (this) {
|
||||
if (mStatus == MAIN_STATUS_STARTED)
|
||||
Bridge.pause();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setPauseOnHeadphonesDisconnect(boolean enabled) {
|
||||
mPauseOnHeadphonesDisconnect = enabled;
|
||||
}
|
||||
|
||||
private void setWakelockEnabled(boolean enabled) {
|
||||
if (enabled && mWakelock == null) {
|
||||
PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
|
||||
mWakelock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG);
|
||||
mWakelock.acquire();
|
||||
Log.d(TAG, "Wakelock acquired");
|
||||
} else if (!enabled && mWakelock != null) {
|
||||
mWakelock.release();
|
||||
mWakelock = null;
|
||||
Log.d(TAG, "Wakelock released");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isRunning() {
|
||||
return mThread != null && mThread.isAlive();
|
||||
}
|
||||
|
||||
private void registerCallback(IMainCallback cb) {
|
||||
if (cb != null) {
|
||||
mCallbacks.register(cb);
|
||||
sendMessage(MSG_SEND_STATUS, mStatus, 0, mError);
|
||||
}
|
||||
}
|
||||
|
||||
private void unregisterCallback(IMainCallback cb) {
|
||||
if (cb != null) {
|
||||
mCallbacks.unregister(cb);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* start Main service without any callback
|
||||
*/
|
||||
public static void startService(Context context, boolean wakelock) {
|
||||
Intent intent = new Intent(context, Main.class)
|
||||
.putExtra("wakelock", wakelock);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
|
||||
/* in Android 8+, we need to use this method
|
||||
or else we'll get "IllegalStateException:
|
||||
app is in background" */
|
||||
context.startForegroundService(intent);
|
||||
else
|
||||
context.startService(intent);
|
||||
}
|
||||
|
||||
public static void stopService(Context context) {
|
||||
Intent intent = new Intent(context, Main.class);
|
||||
context.stopService(intent);
|
||||
}
|
||||
}
|
329
android/app/src/main/java/org/musicpd/Main.kt
Normal file
329
android/app/src/main/java/org/musicpd/Main.kt
Normal file
@ -0,0 +1,329 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
// Copyright The Music Player Daemon Project
|
||||
package org.musicpd
|
||||
|
||||
import android.app.Notification
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.app.Service
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.media.AudioManager
|
||||
import android.os.Build
|
||||
import android.os.IBinder
|
||||
import android.os.Looper
|
||||
import android.os.PowerManager
|
||||
import android.os.PowerManager.WakeLock
|
||||
import android.os.RemoteCallbackList
|
||||
import android.os.RemoteException
|
||||
import android.util.Log
|
||||
import androidx.annotation.OptIn
|
||||
import androidx.core.app.ServiceCompat
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.session.MediaSession
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import org.musicpd.Bridge.LogListener
|
||||
import org.musicpd.data.LoggingRepository
|
||||
import java.lang.reflect.Constructor
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
class Main : Service(), Runnable {
|
||||
companion object {
|
||||
private const val TAG = "Main"
|
||||
private const val WAKELOCK_TAG = "mpd:wakelockmain"
|
||||
|
||||
private const val MAIN_STATUS_ERROR = -1
|
||||
private const val MAIN_STATUS_STOPPED = 0
|
||||
private const val MAIN_STATUS_STARTED = 1
|
||||
|
||||
private const val MSG_SEND_STATUS = 0
|
||||
|
||||
const val SHUTDOWN_ACTION: String = "org.musicpd.action.ShutdownMPD"
|
||||
|
||||
/*
|
||||
* start Main service without any callback
|
||||
*/
|
||||
@JvmStatic
|
||||
fun startService(context: Context, wakelock: Boolean) {
|
||||
val intent = Intent(context, Main::class.java)
|
||||
.putExtra("wakelock", wakelock)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) /* in Android 8+, we need to use this method
|
||||
or else we'll get "IllegalStateException:
|
||||
app is in background" */
|
||||
context.startForegroundService(intent)
|
||||
else context.startService(intent)
|
||||
}
|
||||
}
|
||||
|
||||
private var mThread: Thread? = null
|
||||
private var mStatus = MAIN_STATUS_STOPPED
|
||||
private var mAbort = false
|
||||
private var mError: String? = null
|
||||
private val mCallbacks = RemoteCallbackList<IMainCallback>()
|
||||
private val mBinder: IBinder = MainStub(this)
|
||||
private var mPauseOnHeadphonesDisconnect = false
|
||||
private var mWakelock: WakeLock? = null
|
||||
|
||||
private var mMediaSession: MediaSession? = null
|
||||
|
||||
@JvmField
|
||||
@Inject
|
||||
var logging: LoggingRepository? = null
|
||||
|
||||
internal class MainStub(private val mService: Main) : IMain.Stub() {
|
||||
override fun start() {
|
||||
mService.start()
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
mService.stop()
|
||||
}
|
||||
|
||||
override fun setPauseOnHeadphonesDisconnect(enabled: Boolean) {
|
||||
mService.setPauseOnHeadphonesDisconnect(enabled)
|
||||
}
|
||||
|
||||
override fun setWakelockEnabled(enabled: Boolean) {
|
||||
mService.setWakelockEnabled(enabled)
|
||||
}
|
||||
|
||||
override fun isRunning(): Boolean {
|
||||
return mService.isRunning
|
||||
}
|
||||
|
||||
override fun registerCallback(cb: IMainCallback) {
|
||||
mService.registerCallback(cb)
|
||||
}
|
||||
|
||||
override fun unregisterCallback(cb: IMainCallback) {
|
||||
mService.unregisterCallback(cb)
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun sendMessage(
|
||||
@Suppress("SameParameterValue") what: Int,
|
||||
arg1: Int,
|
||||
arg2: Int,
|
||||
obj: Any?
|
||||
) {
|
||||
var i = mCallbacks.beginBroadcast()
|
||||
while (i > 0) {
|
||||
i--
|
||||
val cb = mCallbacks.getBroadcastItem(i)
|
||||
try {
|
||||
when (what) {
|
||||
MSG_SEND_STATUS -> when (arg1) {
|
||||
MAIN_STATUS_ERROR -> cb.onError(obj as String?)
|
||||
MAIN_STATUS_STOPPED -> cb.onStopped()
|
||||
MAIN_STATUS_STARTED -> cb.onStarted()
|
||||
}
|
||||
}
|
||||
} catch (ignored: RemoteException) {
|
||||
}
|
||||
}
|
||||
mCallbacks.finishBroadcast()
|
||||
}
|
||||
|
||||
private val mLogListener = LogListener { priority, msg ->
|
||||
logging?.addLogItem(priority, msg)
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent): IBinder {
|
||||
return mBinder
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
if (intent?.action == SHUTDOWN_ACTION) {
|
||||
stop()
|
||||
} else {
|
||||
start()
|
||||
if (intent?.getBooleanExtra(
|
||||
"wakelock",
|
||||
false
|
||||
) == true
|
||||
) setWakelockEnabled(true)
|
||||
}
|
||||
return START_REDELIVER_INTENT
|
||||
}
|
||||
|
||||
override fun run() {
|
||||
if (!Loader.loaded) {
|
||||
val error = """
|
||||
Failed to load the native MPD library.
|
||||
Report this problem to us, and include the following information:
|
||||
SUPPORTED_ABIS=${java.lang.String.join(", ", *Build.SUPPORTED_ABIS)}
|
||||
PRODUCT=${Build.PRODUCT}
|
||||
FINGERPRINT=${Build.FINGERPRINT}
|
||||
error=${Loader.error}
|
||||
""".trimIndent()
|
||||
setStatus(MAIN_STATUS_ERROR, error)
|
||||
stopSelf()
|
||||
return
|
||||
}
|
||||
synchronized(this) {
|
||||
if (mAbort) return
|
||||
setStatus(MAIN_STATUS_STARTED, null)
|
||||
}
|
||||
Bridge.run(this, mLogListener)
|
||||
setStatus(MAIN_STATUS_STOPPED, null)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun setStatus(status: Int, error: String?) {
|
||||
mStatus = status
|
||||
mError = error
|
||||
sendMessage(MSG_SEND_STATUS, mStatus, 0, mError)
|
||||
}
|
||||
|
||||
private fun createNotificationBuilderWithChannel(): Notification.Builder? {
|
||||
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as? NotificationManager
|
||||
?: return null
|
||||
|
||||
val id = "org.musicpd"
|
||||
val name = "MPD service"
|
||||
val importance = 3 /* NotificationManager.IMPORTANCE_DEFAULT */
|
||||
|
||||
try {
|
||||
val ncClass = Class.forName("android.app.NotificationChannel")
|
||||
val ncCtor = ncClass.getConstructor(
|
||||
String::class.java,
|
||||
CharSequence::class.java,
|
||||
Int::class.javaPrimitiveType
|
||||
)
|
||||
val nc = ncCtor.newInstance(id, name, importance)
|
||||
|
||||
val nmCreateNotificationChannelMethod =
|
||||
NotificationManager::class.java.getMethod("createNotificationChannel", ncClass)
|
||||
nmCreateNotificationChannelMethod.invoke(notificationManager, nc)
|
||||
|
||||
val nbCtor: Constructor<*> = Notification.Builder::class.java.getConstructor(
|
||||
Context::class.java, String::class.java
|
||||
)
|
||||
return nbCtor.newInstance(this, id) as Notification.Builder
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "error creating the NotificationChannel", e)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(markerClass = [UnstableApi::class])
|
||||
private fun start() {
|
||||
if (mThread != null) return
|
||||
|
||||
val filter = IntentFilter()
|
||||
filter.addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY)
|
||||
registerReceiver(object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
if (!mPauseOnHeadphonesDisconnect) return
|
||||
if (intent.action === AudioManager.ACTION_AUDIO_BECOMING_NOISY) pause()
|
||||
}
|
||||
}, filter)
|
||||
|
||||
val mainIntent = Intent(this, MainActivity::class.java)
|
||||
mainIntent.setAction("android.intent.action.MAIN")
|
||||
mainIntent.addCategory("android.intent.category.LAUNCHER")
|
||||
val contentIntent = PendingIntent.getActivity(
|
||||
this, 0,
|
||||
mainIntent, PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||
)
|
||||
|
||||
val nBuilder: Notification.Builder?
|
||||
if (Build.VERSION.SDK_INT >= 26 /* Build.VERSION_CODES.O */) {
|
||||
nBuilder = createNotificationBuilderWithChannel()
|
||||
if (nBuilder == null) return
|
||||
} else nBuilder = Notification.Builder(this)
|
||||
|
||||
val notification =
|
||||
nBuilder.setContentTitle(getText(R.string.notification_title_mpd_running))
|
||||
.setContentText(getText(R.string.notification_text_mpd_running))
|
||||
.setSmallIcon(R.drawable.notification_icon)
|
||||
.setContentIntent(contentIntent)
|
||||
.build()
|
||||
|
||||
mThread = Thread(this).apply { start() }
|
||||
|
||||
val player = MPDPlayer(Looper.getMainLooper())
|
||||
mMediaSession = MediaSession.Builder(this, player).build()
|
||||
|
||||
startForeground(R.string.notification_title_mpd_running, notification)
|
||||
startService(Intent(this, Main::class.java))
|
||||
}
|
||||
|
||||
private fun stop() {
|
||||
mMediaSession?.let {
|
||||
it.release()
|
||||
mMediaSession = null
|
||||
}
|
||||
mThread?.let { thread ->
|
||||
if (thread.isAlive) {
|
||||
synchronized(this) {
|
||||
if (mStatus == MAIN_STATUS_STARTED) Bridge.shutdown()
|
||||
else mAbort = true
|
||||
}
|
||||
}
|
||||
try {
|
||||
thread.join()
|
||||
mThread = null
|
||||
mAbort = false
|
||||
} catch (ie: InterruptedException) {
|
||||
Log.e(TAG, "failed to join", ie)
|
||||
}
|
||||
}
|
||||
setWakelockEnabled(false)
|
||||
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE)
|
||||
stopSelf()
|
||||
}
|
||||
|
||||
private fun pause() {
|
||||
if (mThread?.isAlive == true) {
|
||||
synchronized(this) {
|
||||
if (mStatus == MAIN_STATUS_STARTED) Bridge.pause()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setPauseOnHeadphonesDisconnect(enabled: Boolean) {
|
||||
mPauseOnHeadphonesDisconnect = enabled
|
||||
}
|
||||
|
||||
private fun setWakelockEnabled(enabled: Boolean) {
|
||||
if (enabled) {
|
||||
val wakeLock =
|
||||
mWakelock ?: run {
|
||||
val pm = getSystemService(POWER_SERVICE) as PowerManager
|
||||
pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG).also {
|
||||
mWakelock = it
|
||||
}
|
||||
}
|
||||
wakeLock.acquire(10 * 60 * 1000L /*10 minutes*/)
|
||||
Log.d(TAG, "Wakelock acquired")
|
||||
} else {
|
||||
mWakelock?.let {
|
||||
it.release()
|
||||
mWakelock = null
|
||||
}
|
||||
Log.d(TAG, "Wakelock released")
|
||||
}
|
||||
}
|
||||
|
||||
private val isRunning: Boolean
|
||||
get() = mThread?.isAlive == true
|
||||
|
||||
private fun registerCallback(cb: IMainCallback?) {
|
||||
if (cb != null) {
|
||||
mCallbacks.register(cb)
|
||||
sendMessage(MSG_SEND_STATUS, mStatus, 0, mError)
|
||||
}
|
||||
}
|
||||
|
||||
private fun unregisterCallback(cb: IMainCallback?) {
|
||||
if (cb != null) {
|
||||
mCallbacks.unregister(cb)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user