Android library module designed to integrate Snapcast functionality into your Android applications.
This project includes the original Snapcast project as a git submodule, compiles it using the Android NDK, and packages it.
You can add the library to your project using either GitHub Packages or JitPack.
Add the following to your project's root build.gradle file:
repositories {
...
maven {
url = uri("https://maven.pkg.github.com/capullo-tech/lib-snapcast-android")
credentials {
username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_USERNAME")
password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN")
}
}
}Please refer to the Github documentation for more information on authenticating to GitHub Packages.
Add the package dependencies to your module's build.gradle file:
dependencies {
implementation 'tech.capullo:lib-snapcast-android:0.29.0'
}Add the following to your project's root build.gradle file:
repositories {
...
maven {
url = uri("https://jitpack.io")
}
}Add the package dependencies to your module's build.gradle file:
dependencies {
implementation 'com.github.capullo-tech.lib-snapcast-android:lib-snapcast-android:main-SNAPSHOT'
}Build number references: https://jitpack.io/#capullo-tech/lib-snapcast-android
Both the snapcast and snapserver binaries are included in the library as shared objects.
val nativeLibraryDir = applicationContext.applicationInfo.nativeLibraryDirYou can then start either the snapcast or snapserver binary using the ProcessBuilder class:
// snapclient
// man pages: https://github.com/badaix/snapcast/blob/master/client/snapclient.1
val androidPlayer = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) "opensl" else "oboe"
val audioManager = applicationContext.getSystemService(Context.AUDIO_SERVICE) as AudioManager
val rate: String? = audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE)
val fpb: String? = audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER)
val sampleformat = "$rate:16:*"
val pb = ProcessBuilder()
.command(
"$nativeLibraryDir/libsnapclient.so",
"--player", androidPlayer,
"--sampleformat", sampleformat,
"<tcp|ws|wss>://<snapserver host or IP or mDNS service name>[:port]" // For example: 'tcp://192.168.1.1:1704', or 'ws://homeserver.local' or 'wss://_snapcast-https._tcp'
)
.redirectErrorStream(true)
val env = pb.environment()
if (rate != null) env["SAMPLE_RATE"] = rate
if (fpb != null) env["FRAMES_PER_BUFFER"] = fpb
val snapclientProcess = pb.start()
// manage the running process
...// snapserver
// man pages: https://github.com/badaix/snapcast/blob/master/server/snapserver.1
val cacheDir = applicationContext.cacheDir
val confFile = File(cacheDir, "snapserver.conf")
val pb = ProcessBuilder()
.command(
"$nativeLibraryDir/libsnapserver.so",
"--config", confFile.absolutePath,
"--server.datadir=$cacheDir",
"--stream.source", "tcp://... OR pipe://... OR) // possible stream source configuration: https://github.com/badaix/snapcast#server
)
.redirectErrorStream(true)
val snapserverProcess = pb.start()
// manage the running process
...Clone this repo with git clone --recurse-submodules or do git submodule update --init --recursive immediately after cloning to initialize the Snapcast submodule
Run:
$ ./gradlew buildFor local development:
$ ./gradlew publishToMavenLocal