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:
Inkeliz
2021-02-21 16:51:39 +00:00
committed by Elias Naur
parent 9d1e3370f4
commit 2a7295750d
+63 -61
View File
@@ -7,6 +7,8 @@ import (
"bytes"
"errors"
"fmt"
"golang.org/x/sync/errgroup"
"golang.org/x/tools/go/packages"
"io"
"io/ioutil"
"os"
@@ -16,9 +18,6 @@ import (
"strconv"
"strings"
"text/template"
"golang.org/x/sync/errgroup"
"golang.org/x/tools/go/packages"
)
type androidTools struct {
@@ -329,15 +328,15 @@ func exeAndroid(tmpDir string, tools *androidTools, bi *buildInfo, extraJars, pe
return nil
})
classFiles = append(classFiles, extraJars...)
apkDir := filepath.Join(tmpDir, "apk")
if err := os.MkdirAll(apkDir, 0755); err != nil {
dexDir := filepath.Join(tmpDir, "apk")
if err := os.MkdirAll(dexDir, 0755); err != nil {
return err
}
if len(classFiles) > 0 {
d8 := exec.Command(
filepath.Join(tools.buildtools, "d8"),
"--classpath", tools.androidjar,
"--output", apkDir,
"--output", dexDir,
)
d8.Args = append(d8.Args, classFiles...)
if _, err := runCmd(d8); err != nil {
@@ -440,60 +439,95 @@ func exeAndroid(tmpDir string, tools *androidTools, bi *buildInfo, extraJars, pe
return err
}
tmpapk := filepath.Join(tmpDir, "link.apk")
linkAPK := filepath.Join(tmpDir, "link.apk")
link := exec.Command(
aapt2,
"link",
"--manifest", manifest,
"-I", tools.androidjar,
"-o", tmpapk,
"-o", linkAPK,
resZip,
)
if _, err := runCmd(link); err != nil {
return err
}
// 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
// classes.dex and the Go libraries.
if err := unzip(apkDir, tmpapk); err != nil {
// files. Copy files from `link.apk` (generated by aapt2) along with classes.dex and
// the Go libraries to a new `app.ap_` file.
// Load link.apk as zip.
linkAPKZip, err := zip.OpenReader(linkAPK)
if err != nil {
return err
}
tmpApk := filepath.Join(tmpDir, "app.ap_")
ap_, err := os.Create(tmpApk)
defer linkAPKZip.Close()
// Create new "APK".
unsignedAPK := filepath.Join(tmpDir, "app.ap_")
unsignedAPKFile, err := os.Create(unsignedAPK)
if err != nil {
return err
}
defer func() {
if cerr := ap_.Close(); err == nil {
if cerr := unsignedAPKFile.Close(); err == nil {
err = cerr
}
}()
apkw := newZipWriter(ap_)
defer apkw.Close()
err = filepath.Walk(apkDir, func(path string, f os.FileInfo, err error) error {
unsignedAPKZip := zip.NewWriter(unsignedAPKFile)
defer unsignedAPKZip.Close()
// 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 {
return err
}
if f.IsDir() {
return nil
r, err := f.Open()
if err != nil {
return err
}
zpath := path[len(apkDir)+1:]
if filepath.Base(path) == "resources.arsc" {
apkw.Store(zpath, path)
} else {
apkw.Add(zpath, path)
if _, err := io.Copy(w, r); err != nil {
return err
}
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
}
// Append Go binaries (libgio.so).
for _, a := range bi.archs {
arch := allArchs[a]
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 {
@@ -553,38 +587,6 @@ func signAPK(tmpDir string, tools *androidTools, bi *buildInfo) error {
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) {
ndks, err := filepath.Glob(filepath.Join(androidHome, "ndk", "*"))
if err != nil {