-
-
Notifications
You must be signed in to change notification settings - Fork 46
/
android.go
200 lines (162 loc) · 4.7 KB
/
android.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
package command
import (
"fmt"
"os"
"path/filepath"
"github.com/fyne-io/fyne-cross/internal/log"
"github.com/fyne-io/fyne-cross/internal/volume"
)
const (
// androidOS is the android OS name
androidOS = "android"
// androidImage is the fyne-cross image for the Android OS
androidImage = "fyneio/fyne-cross:android-latest"
)
// Android build and package the fyne app for the android OS
type Android struct {
Context
}
// Name returns the one word command name
func (cmd *Android) Name() string {
return "android"
}
// Description returns the command description
func (cmd *Android) Description() string {
return "Build and package a fyne application for the android OS"
}
// Parse parses the arguments and set the usage for the command
func (cmd *Android) Parse(args []string) error {
commonFlags, err := newCommonFlags()
if err != nil {
return err
}
flags := &androidFlags{
CommonFlags: commonFlags,
}
flagSet.StringVar(&flags.Keystore, "keystore", "", "The location of .keystore file containing signing information")
flagSet.StringVar(&flags.KeystorePass, "keystore-pass", "", "Password for the .keystore file")
flagSet.StringVar(&flags.KeyPass, "key-pass", "", "Password for the signer's private key, which is needed if the private key is password-protected")
flagSet.Usage = cmd.Usage
flagSet.Parse(args)
ctx, err := makeAndroidContext(flags, flagSet.Args())
if err != nil {
return err
}
cmd.Context = ctx
return nil
}
// Run runs the command
func (cmd *Android) Run() error {
ctx := cmd.Context
log.Infof("[i] Target: %s", ctx.OS)
log.Debugf("%#v", ctx)
//
// pull image, if requested
//
err := pullImage(ctx)
if err != nil {
return err
}
//
// prepare build
//
err = cleanTargetDirs(ctx)
if err != nil {
return err
}
err = goModInit(ctx)
if err != nil {
return err
}
//
// package
//
log.Info("[i] Packaging app...")
packageName := fmt.Sprintf("%s.apk", cmd.Context.Output)
err = prepareIcon(ctx)
if err != nil {
return err
}
if ctx.Release {
err = fyneRelease(ctx)
} else {
err = fynePackage(ctx)
}
if err != nil {
return fmt.Errorf("could not package the Fyne app: %v", err)
}
// move the dist package into the "dist" folder
// The fyne tool sanitizes the package name to be acceptable as a
// android package name. For details, see:
// https://github.com/fyne-io/fyne/blob/v1.4.0/cmd/fyne/internal/mobile/build_androidapp.go#L297
// To avoid to duplicate the fyne tool sanitize logic here, the location of
// the dist package to move will be detected using a matching pattern
apkFilePattern := volume.JoinPathHost(ctx.WorkDirHost(), ctx.Package, "*.apk")
apks, err := filepath.Glob(apkFilePattern)
if err != nil {
return fmt.Errorf("could not find any apk file matching %q: %v", apkFilePattern, err)
}
if apks == nil {
return fmt.Errorf("could not find any apk file matching %q", apkFilePattern)
}
if len(apks) > 1 {
return fmt.Errorf("multiple apk files matching %q: %v. Please remove and build again", apkFilePattern, apks)
}
srcFile := apks[0]
distFile := volume.JoinPathHost(ctx.DistDirHost(), ctx.ID, packageName)
err = os.MkdirAll(filepath.Dir(distFile), 0755)
if err != nil {
return fmt.Errorf("could not create the dist package dir: %v", err)
}
err = os.Rename(srcFile, distFile)
if err != nil {
return err
}
log.Infof("[✓] Package: %s", distFile)
return nil
}
// Usage displays the command usage
func (cmd *Android) Usage() {
data := struct {
Name string
Description string
}{
Name: cmd.Name(),
Description: cmd.Description(),
}
template := `
Usage: fyne-cross {{ .Name }} [options] [package]
{{ .Description }}
Options:
`
printUsage(template, data)
flagSet.PrintDefaults()
}
// androidFlags defines the command-line flags for the android command
type androidFlags struct {
*CommonFlags
Keystore string //Keystore represents the location of .keystore file containing signing information
KeystorePass string //Password for the .keystore file
KeyPass string //Password for the signer's private key, which is needed if the private key is password-protected
}
// makeAndroidContext returns the command context for an android target
func makeAndroidContext(flags *androidFlags, args []string) (Context, error) {
ctx, err := makeDefaultContext(flags.CommonFlags, args)
if err != nil {
return Context{}, err
}
// appID is mandatory for android
if ctx.AppID == "" {
return Context{}, fmt.Errorf("appID is mandatory for %s", androidOS)
}
ctx.OS = androidOS
ctx.ID = androidOS
ctx.Keystore = flags.Keystore
ctx.KeystorePass = flags.KeystorePass
ctx.KeyPass = flags.KeyPass
// set context based on command-line flags
if flags.DockerImage == "" {
ctx.DockerImage = androidImage
}
return ctx, nil
}