diff --git a/gogio/androidbuild.go b/gogio/androidbuild.go
index 79943de..23d21d7 100644
--- a/gogio/androidbuild.go
+++ b/gogio/androidbuild.go
@@ -48,6 +48,7 @@ type manifestData struct {
Features []string
IconSnip string
AppName string
+ Schemes []string
}
const (
@@ -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(
`
@@ -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">
+ {{range .Schemes}}
+
+
+
+
+
+
+ {{end}}
`)
diff --git a/gogio/build_info.go b/gogio/build_info.go
index 1797296..0dc8edc 100644
--- a/gogio/build_info.go
+++ b/gogio/build_info.go
@@ -30,6 +30,7 @@ type buildInfo struct {
notaryAppleID string
notaryPassword string
notaryTeamID string
+ schemes []string
}
type Semver struct {
@@ -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
@@ -72,6 +77,7 @@ func newBuildInfo(pkgPath string) (*buildInfo, error) {
notaryAppleID: *notaryID,
notaryPassword: *notaryPass,
notaryTeamID: *notaryTeamID,
+ schemes: schemes,
}
return bi, nil
}
diff --git a/gogio/help.go b/gogio/help.go
index 2561c2b..b2dfe21 100644
--- a/gogio/help.go
+++ b/gogio/help.go
@@ -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.
`
diff --git a/gogio/iosbuild.go b/gogio/iosbuild.go
index 1126cd5..79b0e2f 100644
--- a/gogio/iosbuild.go
+++ b/gogio/iosbuild.go
@@ -4,6 +4,7 @@ package main
import (
"archive/zip"
+ "bytes"
"crypto/sha1"
"encoding/hex"
"errors"
@@ -14,6 +15,7 @@ import (
"path/filepath"
"strconv"
"strings"
+ "text/template"
"time"
"golang.org/x/sync/errgroup"
@@ -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
@@ -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) {
appName := UppercaseName(bi.name)
platform := iosPlatformFor(bi.target)
var supportPlatform string
@@ -301,36 +306,57 @@ func buildInfoPlist(bi *buildInfo) string {
case "tvos":
supportPlatform = "AppleTVOS"
}
- return fmt.Sprintf(`
+
+ 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(`
CFBundleDevelopmentRegion
en
CFBundleExecutable
- %s
+ {{.AppName}}
CFBundleIdentifier
- %s
+ {{.AppID}}
CFBundleInfoDictionaryVersion
6.0
CFBundleName
- %s
+ {{.AppName}}
CFBundlePackageType
APPL
CFBundleShortVersionString
- %s
+ {{.Version}}
CFBundleVersion
- %d
+ {{.VersionCode}}
UILaunchStoryboardName
LaunchScreen
UIRequiredDeviceCapabilities
arm64
DTPlatformName
- %s
+ {{.Platform}}
DTPlatformVersion
12.4
MinimumOSVersion
- %d
+ {{.MinVersion}}
UIDeviceFamily
1
@@ -338,7 +364,7 @@ func buildInfoPlist(bi *buildInfo) string {
CFBundleSupportedPlatforms
- %s
+ {{.SupportPlatform}}
UISupportedInterfaceOrientations
@@ -353,13 +379,36 @@ func buildInfoPlist(bi *buildInfo) string {
DTSDKBuild
16G73
DTSDKName
- %s12.4
+ {{.Platform}}12.4
DTXcode
1030
DTXcodeBuild
10G8
+ {{if .Schemes}}
+ CFBundleURLTypes
+
+ {{range .Schemes}}
+
+ CFBundleURLSchemes
+
+ {{.}}
+
+
+ {{end}}
+
+ {{end}}
-`, appName, bi.appID, appName, bi.version, bi.version.VersionCode, platform, minIOSVersion, supportPlatform, platform)
+`)
+ 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 {
diff --git a/gogio/macosbuild.go b/gogio/macosbuild.go
index 88e9463..d95e34a 100644
--- a/gogio/macosbuild.go
+++ b/gogio/macosbuild.go
@@ -1,6 +1,7 @@
package main
import (
+ "bytes"
"errors"
"fmt"
"os"
@@ -124,6 +125,19 @@ func (b *macBuilder) setIcon(path string) (err error) {
}
func (b *macBuilder) setInfo(buildInfo *buildInfo, name string) error {
+
+ 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(`
@@ -138,20 +152,28 @@ func (b *macBuilder) setInfo(buildInfo *buildInfo, name string) error {
CFBundlePackageType
APPL
+ {{if .Schemes}}
+ CFBundleURLTypes
+
+ {{range .Schemes}}
+
+ CFBundleURLSchemes
+
+ {{.}}
+
+
+ {{end}}
+
+ {{end}}
`)
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()
diff --git a/gogio/main.go b/gogio/main.go
index 5fe373e..3834710 100644
--- a/gogio/main.go
+++ b/gogio/main.go
@@ -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() {
diff --git a/gogio/windowsbuild.go b/gogio/windowsbuild.go
index c867e03..5404893 100644
--- a/gogio/windowsbuild.go
+++ b/gogio/windowsbuild.go
@@ -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,