Skip to content
This repository was archived by the owner on Oct 26, 2022. It is now read-only.

Add option to preserve service registry #151

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/main/scala/AndroidBase.scala
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,10 @@ object AndroidBase {
useProguard := true,
proguardOptimizations := Seq.empty,

preserveServiceRegistry := false,
serviceRegistryInclude := Seq(".*"),
serviceRegistryExclude := Seq.empty,

jarPath <<= (platformPath, jarName) (_ / _),
libraryJarPath <<= (jarPath (_ get)),

Expand Down
90 changes: 89 additions & 1 deletion src/main/scala/AndroidInstall.scala
Original file line number Diff line number Diff line change
Expand Up @@ -162,13 +162,101 @@ object AndroidInstall {
}
}

private def packageTask(debug: Boolean):Project.Initialize[Task[File]] = (packageConfig, streams) map { (c, s) =>
private def packageTask(debug: Boolean):Project.Initialize[Task[File]] = (packageConfig, fullClasspath, preserveServiceRegistry, serviceRegistryInclude, serviceRegistryExclude, streams) map { (c, cp, p, in, ex, s) =>
val builder = new ApkBuilder(c, debug)
builder.build.fold(sys.error(_), s.log.info(_))
s.log.debug(builder.outputStream.toString)

if (p) {
val services = extractServiceRegistry(cp.files, in, ex)
insertServiceRegistry(c.packageApkPath, services)
}

c.packageApkPath
}

private def extractServiceRegistry(
cp: Seq[JFile], in: Seq[String], ex: Seq[String]
): Map[String, List[String]] = {
import java.util.jar.JarFile
import scala.io.Source
import scala.collection.JavaConversions._

var ret = Map[String, List[String]]()
cp.filter(_.toString.matches(".*\\.jar")).foreach {f => {
val jarfile = new JarFile(f)
try {
for (entry <- jarfile.entries()) {
val name = entry.getName()
if (name.matches("META-INF/services/..*")) {
val is = jarfile.getInputStream(entry)
try {
val lns = Source.fromInputStream(is).getLines().
filter(cls => in.exists(r => cls.matches(r))).
filter(cls => ex.forall(r => !cls.matches(r)))
ret += name -> (ret.getOrElse(name, List()) ++ lns)
}
finally {
is.close()
}
}
}
}
finally {
jarfile.close()
}
}}

ret
}

private def insertServiceRegistry(apk: File,
services: Map[String, List[String]]) = {
import java.util.zip.ZipOutputStream
import java.util.zip.ZipInputStream
import java.util.zip.ZipEntry
import java.io.FileOutputStream
import java.io.FileInputStream
import java.io.File

val tmp = new File(apk.getAbsolutePath + ".tmp")
tmp.delete()

if (!apk.renameTo(tmp)) {
throw new RuntimeException("could not rename file " + apk)
}
val buf = Array.ofDim[Byte](1024)

val in = new ZipInputStream(new FileInputStream(tmp))
val out = new ZipOutputStream(new FileOutputStream(apk))

try {
var entry = in.getNextEntry()

while (entry != null) {
out.putNextEntry(new ZipEntry(entry.getName))
var len = in.read(buf)
while (len > 0) {
out.write(buf, 0, len)
len = in.read(buf)
}
entry = in.getNextEntry()
}

for ((name, value) <- services) {
if (value.size > 0) {
out.putNextEntry(new ZipEntry(name))
out.write(value.mkString("\n").getBytes)
}
}
}
finally {
tmp.delete()
in.close()
out.close()
}
}

lazy val installerTasks = Seq (
installEmulator <<= installTask(emulator = true) dependsOn packageDebug,
installDevice <<= installTask(emulator = false) dependsOn packageDebug
Expand Down
6 changes: 5 additions & 1 deletion src/main/scala/AndroidKeys.scala
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ object AndroidKeys {
val packageApkLibPath = TaskKey[File]("package-apklib-path")
val useProguard = SettingKey[Boolean]("use-proguard")

val preserveServiceRegistry = SettingKey[Boolean]("preserve-service-registry")
val serviceRegistryInclude = SettingKey[Seq[String]]("service-registry-include")
val serviceRegistryExclude = SettingKey[Seq[String]]("service-registry-exclude")

/** Install Settings */
val packageConfig = TaskKey[ApkConfig]("package-config",
"Generates a Apk Config")
Expand All @@ -81,7 +85,7 @@ object AndroidKeys {
val typedResource = TaskKey[File]("typed-resource",
"""Typed resource file to be generated, also includes
interfaces to access these resources.""")
val layoutResources = TaskKey[Seq[File]]("layout-resources",
val layoutResources = TaskKey[Seq[File]]("layout-resources",
"""All files that are in res/layout. They will
be accessable through TR.layouts._""")

Expand Down