Skip to content
11 changes: 11 additions & 0 deletions gogio/androidbuild.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ type manifestData struct {
Features []string
IconSnip string
AppName string
Schemes []string
}

const (
Expand Down Expand Up @@ -445,6 +446,7 @@ func exeAndroid(tmpDir string, tools *androidTools, bi *buildInfo, extraJars, pe
Features: features,
IconSnip: iconSnip,
AppName: appName,
Schemes: bi.schemes,
}
tmpl, err := template.New("test").Parse(
`<?xml version="1.0" encoding="utf-8"?>
Expand All @@ -461,11 +463,20 @@ func exeAndroid(tmpDir string, tools *androidTools, bi *buildInfo, extraJars, pe
android:theme="@style/Theme.GioApp"
android:configChanges="screenSize|screenLayout|smallestScreenSize|orientation|keyboardHidden"
android:windowSoftInputMode="adjustResize"
android:launchMode= "singleInstance"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
{{range .Schemes}}
<intent-filter>
<action android:name="android.intent.action.VIEW"></action>
<category android:name="android.intent.category.DEFAULT"></category>
<category android:name="android.intent.category.BROWSABLE"></category>
<data android:scheme="{{.}}"></data>
</intent-filter>
{{end}}
</activity>
</application>
</manifest>`)
Expand Down
6 changes: 6 additions & 0 deletions gogio/build_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type buildInfo struct {
notaryAppleID string
notaryPassword string
notaryTeamID string
schemes []string
}

type Semver struct {
Expand All @@ -51,6 +52,10 @@ func newBuildInfo(pkgPath string) (*buildInfo, error) {
if *name != "" {
appName = *name
}
schemes := strings.Split(*schemes, ",")
for i, scheme := range schemes {
schemes[i] = strings.TrimSpace(scheme)
}
ver, err := parseSemver(*version)
if err != nil {
return nil, err
Expand All @@ -72,6 +77,7 @@ func newBuildInfo(pkgPath string) (*buildInfo, error) {
notaryAppleID: *notaryID,
notaryPassword: *notaryPass,
notaryTeamID: *notaryTeamID,
schemes: schemes,
}
return bi, nil
}
Expand Down
5 changes: 5 additions & 0 deletions gogio/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,9 @@ for details. If not provided, the password will be prompted.

The -notaryteamid flag specifies the team ID to use for notarization of MacOS app, ignored if
-notaryid is not provided.

The -schemes flag specifies a list of comma separated URI schemes that the program can
handle. For example, use -schemes yourAppName to receive a transfer.URLEvent for URIs
starting with yourAppName://. It is only supported on Android, iOS, macOS and Windows.
On Windows, it will restrict the program to a single instance.
`
75 changes: 62 additions & 13 deletions gogio/iosbuild.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package main

import (
"archive/zip"
"bytes"
"crypto/sha1"
"encoding/hex"
"errors"
Expand All @@ -14,6 +15,7 @@ import (
"path/filepath"
"strconv"
"strings"
"text/template"
"time"

"golang.org/x/sync/errgroup"
Expand Down Expand Up @@ -203,7 +205,10 @@ func exeIOS(tmpDir, target, app string, bi *buildInfo) error {
if _, err := runCmd(lipo); err != nil {
return err
}
infoPlist := buildInfoPlist(bi)
infoPlist, err := buildInfoPlist(bi)
if err != nil {
return err
}
plistFile := filepath.Join(app, "Info.plist")
if err := os.WriteFile(plistFile, []byte(infoPlist), 0660); err != nil {
return err
Expand Down Expand Up @@ -291,7 +296,7 @@ func iosIcons(bi *buildInfo, tmpDir, appDir, icon string) (string, error) {
return assetPlist, err
}

func buildInfoPlist(bi *buildInfo) string {
func buildInfoPlist(bi *buildInfo) (string, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this function can return a non-nil error anymore.

appName := UppercaseName(bi.name)
platform := iosPlatformFor(bi.target)
var supportPlatform string
Expand All @@ -301,44 +306,65 @@ func buildInfoPlist(bi *buildInfo) string {
case "tvos":
supportPlatform = "AppleTVOS"
}
return fmt.Sprintf(`<?xml version="1.0" encoding="UTF-8"?>

manifestSrc := struct {
AppName string
AppID string
Version string
VersionCode uint32
Platform string
MinVersion int
SupportPlatform string
Schemes []string
}{
AppName: appName,
AppID: bi.appID,
Version: bi.version.String(),
VersionCode: bi.version.VersionCode,
Platform: platform,
MinVersion: minIOSVersion,
SupportPlatform: supportPlatform,
Schemes: bi.schemes,
}

tmpl, err := template.New("manifest").Parse(`<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>%s</string>
<string>{{.AppName}}</string>
<key>CFBundleIdentifier</key>
<string>%s</string>
<string>{{.AppID}}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>%s</string>
<string>{{.AppName}}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>%s</string>
<string>{{.Version}}</string>
<key>CFBundleVersion</key>
<string>%d</string>
<string>{{.VersionCode}}</string>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array><string>arm64</string></array>
<key>DTPlatformName</key>
<string>%s</string>
<string>{{.Platform}}</string>
<key>DTPlatformVersion</key>
<string>12.4</string>
<key>MinimumOSVersion</key>
<string>%d</string>
<string>{{.MinVersion}}</string>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>%s</string>
<string>{{.SupportPlatform}}</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
Expand All @@ -353,13 +379,36 @@ func buildInfoPlist(bi *buildInfo) string {
<key>DTSDKBuild</key>
<string>16G73</string>
<key>DTSDKName</key>
<string>%s12.4</string>
<string>{{.Platform}}12.4</string>
<key>DTXcode</key>
<string>1030</string>
<key>DTXcodeBuild</key>
<string>10G8</string>
{{if .Schemes}}
<key>CFBundleURLTypes</key>
<array>
{{range .Schemes}}
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>{{.}}</string>
</array>
</dict>
{{end}}
</array>
{{end}}
</dict>
</plist>`, appName, bi.appID, appName, bi.version, bi.version.VersionCode, platform, minIOSVersion, supportPlatform, platform)
</plist>`)
if err != nil {
panic(err)
}

var manifestBuffer bytes.Buffer
if err := tmpl.Execute(&manifestBuffer, manifestSrc); err != nil {
panic(err)
}

return manifestBuffer.String(), nil
}

func iosPlatformFor(target string) string {
Expand Down
40 changes: 31 additions & 9 deletions gogio/macosbuild.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"bytes"
"errors"
"fmt"
"os"
Expand Down Expand Up @@ -124,6 +125,19 @@ func (b *macBuilder) setIcon(path string) (err error) {
}

func (b *macBuilder) setInfo(buildInfo *buildInfo, name string) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.


manifestSrc := struct {
Name string
Bundle string
Version Semver
Schemes []string
}{
Name: name,
Bundle: buildInfo.appID,
Version: buildInfo.version,
Schemes: buildInfo.schemes,
}

t, err := template.New("manifest").Parse(`<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
Expand All @@ -138,20 +152,28 @@ func (b *macBuilder) setInfo(buildInfo *buildInfo, name string) error {
<true/>
<key>CFBundlePackageType</key>
<string>APPL</string>
{{if .Schemes}}
<key>CFBundleURLTypes</key>
<array>
{{range .Schemes}}
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>{{.}}</string>
</array>
</dict>
{{end}}
</array>
{{end}}
</dict>
</plist>`)
if err != nil {
return err
panic(err)
}

var manifest bufferCoff
if err := t.Execute(&manifest, struct {
Name, Bundle string
}{
Name: name,
Bundle: buildInfo.appID,
}); err != nil {
return err
var manifest bytes.Buffer
if err := t.Execute(&manifest, manifestSrc); err != nil {
panic(err)
}
b.Manifest = manifest.Bytes()

Expand Down
1 change: 1 addition & 0 deletions gogio/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ var (
notaryID = flag.String("notaryid", "", "specify the apple id to use for notarization.")
notaryPass = flag.String("notarypass", "", "specify app-specific password of the Apple ID to be used for notarization.")
notaryTeamID = flag.String("notaryteamid", "", "specify the team id to use for notarization.")
schemes = flag.String("schemes", "", "specify a list of comma separated deep-linking schemes that the program accepts")
)

func main() {
Expand Down
10 changes: 9 additions & 1 deletion gogio/windowsbuild.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,10 +202,18 @@ func (b *windowsBuilder) buildProgram(buildInfo *buildInfo, name string, arch st
dest = filepath.Join(filepath.Dir(b.DestDir), name+"_"+arch+".exe")
}

ldflags := buildInfo.ldflags
if buildInfo.schemes != nil {
ldflags += ` -X "gioui.org/app.schemesURI=` + strings.Join(buildInfo.schemes, ",") + `" `
}
if buildInfo.appID != "" {
ldflags += ` -X "gioui.org/app.ID=` + buildInfo.appID + `" `
}

cmd := exec.Command(
"go",
"build",
"-ldflags=-H=windowsgui "+buildInfo.ldflags,
"-ldflags=-H=windowsgui "+ldflags,
"-tags="+buildInfo.tags,
"-o", dest,
buildInfo.pkgPath,
Expand Down