Skip to content

Commit

Permalink
v0.8.0-pre4: compileSdkPreview = VIC is moved to new ktmidi-android-e…
Browse files Browse the repository at this point in the history
…xt module.

We need to keep ktmidi not injected by preview SDK because that will require
any dependent libraries and apps to compile with VIC. That will result in
being prohibited to publish to Play Store, which is not acceptable.

To workaround the issue, isolated MidiUmpDeviceService support to another
dedicated module.
  • Loading branch information
atsushieno committed Mar 7, 2024
1 parent 434c88e commit fddfafb
Show file tree
Hide file tree
Showing 16 changed files with 221 additions and 134 deletions.
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ plugins {
alias(libs.plugins.dokka) apply false
alias(libs.plugins.gradleJavacppPlatform) apply false
alias(libs.plugins.binaryCompatibilityValidatorPlugin) apply false
alias(libs.plugins.kotlinAndroid) apply false
}

allprojects {
group = 'dev.atsushieno'
version = '0.8.0-pre3'
version = '0.8.0-pre4'
}

apply from: "${rootDir}/publish-root.gradle"
Expand Down
1 change: 1 addition & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ gradleJavacppBuild = { id = "org.bytedeco.gradle-javacpp-build", version.ref = "
gradleJavacppPlatform = { id = "org.bytedeco.gradle-javacpp-platform", version.ref = "gradle-javacpp" }
kotlinSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
binaryCompatibilityValidatorPlugin = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "binary-compatibility-validator" }
kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }

[bundles]

47 changes: 47 additions & 0 deletions ktmidi-android-ext/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed
plugins {
alias(libs.plugins.androidLibrary)
alias(libs.plugins.kotlinAndroid)
alias(libs.plugins.dokka)
id("maven-publish")
id("signing")
}

android {
namespace = "dev.atsushieno.ktmidi.androidext"
compileSdkPreview = "VanillaIceCream"

defaultConfig {
minSdk = 23

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
}

buildTypes {
release {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}

dependencies {
implementation(project(":ktmidi"))

testImplementation(libs.junit)
androidTestImplementation(libs.androidx.test.junit)
androidTestImplementation(libs.androidx.espresso.core)
}


ext["moduleDescription"] = "Kotlin Multiplatform library for MIDI 1.0 and MIDI 2.0 - Android Extensions"

apply { from("../publish-pom.gradle") }
Empty file.
21 changes: 21 additions & 0 deletions ktmidi-android-ext/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package dev.atsushieno.ktmidi.androidext

import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4

import org.junit.Test
import org.junit.runner.RunWith

import org.junit.Assert.*

/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("dev.atsushieno.ktmidi.androidext.test", appContext.packageName)
}
}
5 changes: 5 additions & 0 deletions ktmidi-android-ext/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package dev.atsushieno.ktmidi

import android.content.Context
import android.media.midi.MidiDeviceInfo
import android.media.midi.MidiManager
import android.os.Build

class AndroidMidi2Access(applicationContext: Context, private val includeMidi1Transport: Boolean = false) : AndroidMidiAccess(applicationContext) {
override val ports : List<MidiPortDetails>
get() =
(if (includeMidi1Transport) ports1 else listOf())
.flatMap { d -> d.ports.map { port -> Pair(d, port) } }
.map { pair -> AndroidPortDetails(pair.first, pair.second, 1) } +
ports2.flatMap { d -> d.ports.map { port -> Pair(d, port) } }
.map { pair -> AndroidPortDetails(pair.first, pair.second, 2) }
private val ports2: List<MidiDeviceInfo>
get() =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
manager.getDevicesForTransport(MidiManager.TRANSPORT_UNIVERSAL_MIDI_PACKETS).toList()
else
manager.devices.toList()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package dev.atsushieno.ktmidi.androidext

import org.junit.Test

import org.junit.Assert.*

/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}
1 change: 1 addition & 0 deletions ktmidi-ci-tool/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ kotlin {
implementation(libs.compose.ui.tooling.preview)
implementation(libs.androidx.activity.compose)
implementation(libs.kotlinx.coroutines.android)
implementation(project(":ktmidi-android-ext"))
implementation(libs.mpfilepicker)
}
commonMain.dependencies {
Expand Down
56 changes: 2 additions & 54 deletions ktmidi-ci/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -134,58 +134,6 @@ android {
}
}

afterEvaluate {
publishing {
publications.withType<MavenPublication> {
// https://github.com/gradle/gradle/issues/26091#issuecomment-1681343496
val dokkaJar = project.tasks.register("${name}DokkaJar", Jar::class) {
group = JavaBasePlugin.DOCUMENTATION_GROUP
description = "Assembles Kotlin docs with Dokka into a Javadoc jar"
archiveClassifier.set("javadoc")
from(tasks.named("dokkaHtml"))
ext["moduleDescription"] = "Kotlin Multiplatform library for MIDI 1.0 and MIDI 2.0 - MIDI-CI support"

// Each archive name should be distinct, to avoid implicit dependency issues.
// We use the same format as the sources Jar tasks.
// https://youtrack.jetbrains.com/issue/KT-46466
archiveBaseName.set("${archiveBaseName.get()}-${name}")
}
artifact(dokkaJar)

pom {
name.set("ktmidi-ci")
description.set("Kotlin Multiplatform library for MIDI 1.0 and MIDI 2.0 - MIDI-CI support")
url.set("https://github.com/atsushieno/ktmidi")
scm {
url.set("https://github.com/atsushieno/ktmidi")
}
licenses {
license {
name.set("the MIT License")
url.set("https://github.com/atsushieno/ktmidi/blob/main/LICENSE")
}
}
developers {
developer {
id.set("atsushieno")
name.set("Atsushi Eno")
email.set("atsushieno@gmail.com")
}
}
}
}

repositories {
maven {
name = "OSSRH"
url = uri("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/")
credentials {
username = System.getenv("OSSRH_USERNAME")
password = System.getenv("OSSRH_PASSWORD")
}
}
}
}

// keep it as is. It is replaced by CI release builds
signing {}
}
apply { from("../publish-pom.gradle") }
18 changes: 13 additions & 5 deletions ktmidi/api/android/ktmidi.api
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
public final class dev/atsushieno/ktmidi/AndroidMidi2Access : dev/atsushieno/ktmidi/AndroidMidiAccess {
public fun <init> (Landroid/content/Context;Z)V
public synthetic fun <init> (Landroid/content/Context;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
}

public class dev/atsushieno/ktmidi/AndroidMidiAccess : dev/atsushieno/ktmidi/MidiAccess {
public fun <init> (Landroid/content/Context;)V
public fun getInputs ()Ljava/lang/Iterable;
public final fun getManager ()Landroid/media/midi/MidiManager;
public fun getName ()Ljava/lang/String;
public fun getOutputs ()Ljava/lang/Iterable;
protected fun getPorts ()Ljava/util/List;
public final fun getPorts1 ()Ljava/util/List;
public fun openInput (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun openOutput (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public final class dev/atsushieno/ktmidi/AndroidPortDetails : dev/atsushieno/ktmidi/MidiPortDetails {
public fun <init> (Landroid/media/midi/MidiDeviceInfo;Landroid/media/midi/MidiDeviceInfo$PortInfo;I)V
public final fun getDevice ()Landroid/media/midi/MidiDeviceInfo;
public fun getId ()Ljava/lang/String;
public fun getManufacturer ()Ljava/lang/String;
public fun getMidiTransportProtocol ()I
public fun getName ()Ljava/lang/String;
public final fun getPortInfo ()Landroid/media/midi/MidiDeviceInfo$PortInfo;
public fun getVersion ()Ljava/lang/String;
}

public final class dev/atsushieno/ktmidi/ByteOrder : java/lang/Enum {
public static final field BIG_ENDIAN Ldev/atsushieno/ktmidi/ByteOrder;
public static final field Companion Ldev/atsushieno/ktmidi/ByteOrder$Companion;
Expand Down
58 changes: 3 additions & 55 deletions ktmidi/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetWithTests
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl

plugins {
alias(libs.plugins.androidLibrary)
alias(libs.plugins.kotlinMultiplatform)
alias(libs.plugins.androidLibrary)
alias(libs.plugins.dokka)
alias(libs.plugins.binaryCompatibilityValidatorPlugin)
id("maven-publish")
Expand Down Expand Up @@ -179,58 +179,6 @@ android {
}
}

afterEvaluate {
publishing {
publications.withType<MavenPublication> {
// https://github.com/gradle/gradle/issues/26091#issuecomment-1681343496
val dokkaJar = project.tasks.register("${name}DokkaJar", Jar::class) {
group = JavaBasePlugin.DOCUMENTATION_GROUP
description = "Assembles Kotlin docs with Dokka into a Javadoc jar"
archiveClassifier.set("javadoc")
from(tasks.named("dokkaHtml"))

// Each archive name should be distinct, to avoid implicit dependency issues.
// We use the same format as the sources Jar tasks.
// https://youtrack.jetbrains.com/issue/KT-46466
archiveBaseName.set("${archiveBaseName.get()}-${name}")
}
artifact(dokkaJar)

pom {
name.set("ktmidi")
description.set("Kotlin Multiplatform library for MIDI 1.0 and MIDI 2.0")
url.set("https://github.com/atsushieno/ktmidi")
scm {
url.set("https://github.com/atsushieno/ktmidi")
}
licenses {
license {
name.set("the MIT License")
url.set("https://github.com/atsushieno/ktmidi/blob/main/LICENSE")
}
}
developers {
developer {
id.set("atsushieno")
name.set("Atsushi Eno")
email.set("atsushieno@gmail.com")
}
}
}
}

repositories {
maven {
name = "OSSRH"
url = uri("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/")
credentials {
username = System.getenv("OSSRH_USERNAME")
password = System.getenv("OSSRH_PASSWORD")
}
}
}
}
ext["moduleDescription"] = "Kotlin Multiplatform library for MIDI 1.0 and MIDI 2.0"

// keep it as is. It is replaced by CI release builds
signing {}
}
apply { from("../publish-pom.gradle") }
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,16 @@ import android.os.Build
import android.os.Build.VERSION_CODES
import kotlinx.coroutines.delay

class AndroidMidi2Access(applicationContext: Context, private val includeMidi1Transport: Boolean = false) : AndroidMidiAccess(applicationContext) {
override val ports : List<MidiPortDetails>
get() =
(if (includeMidi1Transport) ports1 else listOf())
.flatMap { d -> d.ports.map { port -> Pair(d, port) } }
.map { pair -> AndroidPortDetails(pair.first, pair.second, 1) } +
ports2.flatMap { d -> d.ports.map { port -> Pair(d, port) } }
.map { pair -> AndroidPortDetails(pair.first, pair.second, 2) }
private val ports2: List<MidiDeviceInfo>
get() =
if (Build.VERSION.SDK_INT >= VERSION_CODES.TIRAMISU)
manager.getDevicesForTransport(MidiManager.TRANSPORT_UNIVERSAL_MIDI_PACKETS).toList()
else
manager.devices.toList()
}

open class AndroidMidiAccess(applicationContext: Context) : MidiAccess() {
override val name: String
get() = "AndroidSDK"

internal val manager: MidiManager = applicationContext.getSystemService(Service.MIDI_SERVICE) as MidiManager
val manager: MidiManager = applicationContext.getSystemService(Service.MIDI_SERVICE) as MidiManager
protected open val ports : List<MidiPortDetails>
get() = ports1.flatMap { d -> d.ports.map { port -> Pair(d, port) } }
.map { pair -> AndroidPortDetails(pair.first, pair.second, 1) }
@Suppress("DEPRECATION") // cannot linter track this conditional code while it can detect unguarded invocation?
internal val ports1: List<MidiDeviceInfo>
val ports1: List<MidiDeviceInfo>
get() =
if (Build.VERSION.SDK_INT >= VERSION_CODES.TIRAMISU)
manager.getDevicesForTransport(MidiManager.TRANSPORT_MIDI_BYTE_STREAM).toList()
Expand Down Expand Up @@ -61,7 +45,7 @@ open class AndroidMidiAccess(applicationContext: Context) : MidiAccess() {
}
}

private class AndroidPortDetails(val device: MidiDeviceInfo, val portInfo: MidiDeviceInfo.PortInfo,
class AndroidPortDetails(val device: MidiDeviceInfo, val portInfo: MidiDeviceInfo.PortInfo,
override val midiTransportProtocol: Int
) : MidiPortDetails {
private val significantPortName = if (portInfo.name != "input" && portInfo.name != "output") portInfo.name else null
Expand Down
Loading

0 comments on commit fddfafb

Please sign in to comment.