mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-03 08:25:34 +00:00
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"
|
||||
"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 {
|
||||
|
||||
Reference in New Issue
Block a user