forked from joejulian/gio
cmd/gogio: fix icon/resources for Android
Previously that patch, gogio unzip the `link.apk` (generated by AAPT2) to an temporary folder and then compress it again to a new `app.ap_` file. For some unknown reason, that unzip-then-zip doesn't work. The resources are included but is corrupted in somehow. That PR aims to fix that by avoid the extraction to an temporary folder. Signed-off-by: Inkeliz <inkeliz@inkeliz.com>
This commit is contained in:
+63
-61
@@ -7,6 +7,8 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
"golang.org/x/tools/go/packages"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
@@ -16,9 +18,6 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"golang.org/x/sync/errgroup"
|
|
||||||
"golang.org/x/tools/go/packages"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type androidTools struct {
|
type androidTools struct {
|
||||||
@@ -329,15 +328,15 @@ func exeAndroid(tmpDir string, tools *androidTools, bi *buildInfo, extraJars, pe
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
classFiles = append(classFiles, extraJars...)
|
classFiles = append(classFiles, extraJars...)
|
||||||
apkDir := filepath.Join(tmpDir, "apk")
|
dexDir := filepath.Join(tmpDir, "apk")
|
||||||
if err := os.MkdirAll(apkDir, 0755); err != nil {
|
if err := os.MkdirAll(dexDir, 0755); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(classFiles) > 0 {
|
if len(classFiles) > 0 {
|
||||||
d8 := exec.Command(
|
d8 := exec.Command(
|
||||||
filepath.Join(tools.buildtools, "d8"),
|
filepath.Join(tools.buildtools, "d8"),
|
||||||
"--classpath", tools.androidjar,
|
"--classpath", tools.androidjar,
|
||||||
"--output", apkDir,
|
"--output", dexDir,
|
||||||
)
|
)
|
||||||
d8.Args = append(d8.Args, classFiles...)
|
d8.Args = append(d8.Args, classFiles...)
|
||||||
if _, err := runCmd(d8); err != nil {
|
if _, err := runCmd(d8); err != nil {
|
||||||
@@ -440,60 +439,95 @@ func exeAndroid(tmpDir string, tools *androidTools, bi *buildInfo, extraJars, pe
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpapk := filepath.Join(tmpDir, "link.apk")
|
linkAPK := filepath.Join(tmpDir, "link.apk")
|
||||||
link := exec.Command(
|
link := exec.Command(
|
||||||
aapt2,
|
aapt2,
|
||||||
"link",
|
"link",
|
||||||
"--manifest", manifest,
|
"--manifest", manifest,
|
||||||
"-I", tools.androidjar,
|
"-I", tools.androidjar,
|
||||||
"-o", tmpapk,
|
"-o", linkAPK,
|
||||||
resZip,
|
resZip,
|
||||||
)
|
)
|
||||||
if _, err := runCmd(link); err != nil {
|
if _, err := runCmd(link); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// The Go standard library archive/zip doesn't support appending to zip
|
// The Go standard library archive/zip doesn't support appending to zip
|
||||||
// files. Unpack the apk from aapt2 and re-zip its contents along with
|
// files. Copy files from `link.apk` (generated by aapt2) along with classes.dex and
|
||||||
// classes.dex and the Go libraries.
|
// the Go libraries to a new `app.ap_` file.
|
||||||
if err := unzip(apkDir, tmpapk); err != nil {
|
|
||||||
|
// Load link.apk as zip.
|
||||||
|
linkAPKZip, err := zip.OpenReader(linkAPK)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
tmpApk := filepath.Join(tmpDir, "app.ap_")
|
defer linkAPKZip.Close()
|
||||||
ap_, err := os.Create(tmpApk)
|
|
||||||
|
// Create new "APK".
|
||||||
|
unsignedAPK := filepath.Join(tmpDir, "app.ap_")
|
||||||
|
unsignedAPKFile, err := os.Create(unsignedAPK)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if cerr := ap_.Close(); err == nil {
|
if cerr := unsignedAPKFile.Close(); err == nil {
|
||||||
err = cerr
|
err = cerr
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
apkw := newZipWriter(ap_)
|
unsignedAPKZip := zip.NewWriter(unsignedAPKFile)
|
||||||
defer apkw.Close()
|
defer unsignedAPKZip.Close()
|
||||||
err = filepath.Walk(apkDir, func(path string, f os.FileInfo, err error) error {
|
|
||||||
|
// Copy files from linkAPK to unsignedAPK.
|
||||||
|
for _, f := range linkAPKZip.File {
|
||||||
|
header := zip.FileHeader{
|
||||||
|
Name: f.FileHeader.Name,
|
||||||
|
Method: f.FileHeader.Method,
|
||||||
|
}
|
||||||
|
|
||||||
|
w, err := unsignedAPKZip.CreateHeader(&header)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if f.IsDir() {
|
r, err := f.Open()
|
||||||
return nil
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
zpath := path[len(apkDir)+1:]
|
if _, err := io.Copy(w, r); err != nil {
|
||||||
if filepath.Base(path) == "resources.arsc" {
|
return err
|
||||||
apkw.Store(zpath, path)
|
|
||||||
} else {
|
|
||||||
apkw.Add(zpath, path)
|
|
||||||
}
|
}
|
||||||
return nil
|
}
|
||||||
})
|
|
||||||
if err != nil {
|
// Append new files (that doesn't exists inside the link.apk).
|
||||||
|
appendToZip := func(path string, file string) error {
|
||||||
|
f, err := os.Open(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
w, err := unsignedAPKZip.CreateHeader(&zip.FileHeader{
|
||||||
|
Name: filepath.ToSlash(path),
|
||||||
|
Method: zip.Deflate,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = io.Copy(w, f)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Append Go binaries (libgio.so).
|
||||||
for _, a := range bi.archs {
|
for _, a := range bi.archs {
|
||||||
arch := allArchs[a]
|
arch := allArchs[a]
|
||||||
libFile := filepath.Join(arch.jniArch, "libgio.so")
|
libFile := filepath.Join(arch.jniArch, "libgio.so")
|
||||||
apkw.Add(filepath.ToSlash(filepath.Join("lib", libFile)), filepath.Join(tmpDir, "jni", libFile))
|
if err := appendToZip(filepath.Join("lib", libFile), filepath.Join(tmpDir, "jni", libFile)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return apkw.Close()
|
|
||||||
|
// Append classes.dex.
|
||||||
|
if err := appendToZip("classes.dex", filepath.Join(dexDir, "classes.dex")); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return unsignedAPKZip.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func signAPK(tmpDir string, tools *androidTools, bi *buildInfo) error {
|
func signAPK(tmpDir string, tools *androidTools, bi *buildInfo) error {
|
||||||
@@ -553,38 +587,6 @@ func signAPK(tmpDir string, tools *androidTools, bi *buildInfo) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func unzip(dir, zipfile string) (err error) {
|
|
||||||
zipr, err := zip.OpenReader(zipfile)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer zipr.Close()
|
|
||||||
for _, f := range zipr.File {
|
|
||||||
path := filepath.Join(dir, f.Name)
|
|
||||||
if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
out, err := os.Create(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
if cerr := out.Close(); err == nil {
|
|
||||||
err = cerr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
in, err := f.Open()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer in.Close()
|
|
||||||
if _, err := io.Copy(out, in); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func findNDK(androidHome string) (string, error) {
|
func findNDK(androidHome string) (string, error) {
|
||||||
ndks, err := filepath.Glob(filepath.Join(androidHome, "ndk", "*"))
|
ndks, err := filepath.Glob(filepath.Join(androidHome, "ndk", "*"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user