Xamarin.Forms - iOS 链接到 http 方案 url 的应用程序不起作用
Xamarin.Forms - iOS app linking to an http scheme url doesn't work
我正在为 Android 和 iOS 使用 Xamarin.Forms 开发一个应用程序。当我输入类似于 http://app.myapp.io/user/reset-password/{some_hash}
的 url 时,我会在一个特殊屏幕中打开该应用程序,该屏幕允许用户为其帐户设置新密码。
在 Android 中,我通过使用自定义意图过滤器实现了这一点,将方案设置为 http
并将主机设置为 app.myapp.io
。我想在 iOS 中做同样的事情。但是据我所知,当您在 iOS 中注册应用程序链接时,方法是在您的 Info.plist
文件中注册自定义方案。这是我 Info.plist
文件中的自定义方案。
<?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>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>MinimumOSVersion</key>
<string>6.0</string>
<key>CFBundleDisplayName</key>
<string>MyApp</string>
<key>CFBundleIdentifier</key>
<string>com.company.app</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>CFBundleIconFiles</key>
<array>
<string>Icon-60@2x</string>
<string>Icon-60@3x</string>
<string>Icon-76</string>
<string>Icon-76@2x</string>
<string>Default</string>
<string>Default@2x</string>
<string>Default-568h@2x</string>
<string>Default-Portrait</string>
<string>Default-Portrait@2x</string>
<string>Icon-Small-40</string>
<string>Icon-Small-40@2x</string>
<string>Icon-Small-40@3x</string>
<string>Icon-Small</string>
<string>Icon-Small@2x</string>
<string>Icon-Small@3x</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>CFBundleName</key>
<string>Halligan</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>com.company.app</string>
<key>CFBundleURLSchemes</key>
<array>
<string>http</string>
</array>
</dict>
</array>
</dict>
</plist>
这是我的 AppDelegate.cs
{
// The UIApplicationDelegate for the application. This class is responsible for launching the
// User Interface of the application, as well as listening (and optionally responding) to
// application events from iOS.
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate, IDeviceStorage
{
const string HOCKEYAPP_APPID = "ef71d53e56044baa813c2381b291c355";
#region IDeviceStorage implementation
public string LoadString(string key, string def = null)
{
string value = NSUserDefaults.StandardUserDefaults.StringForKey(key);
if (value == null)
return def;
else
return value;
}
public void SaveString(string key, string value)
{
NSUserDefaults.StandardUserDefaults.SetString(value, key);
NSUserDefaults.StandardUserDefaults.Synchronize();
}
#endregion
//
// This method is invoked when the application has loaded and is ready to run. In this
// method you should instantiate the window, load the UI into it and then make the window
// visible.
//
// You have 17 seconds to return from this method, or iOS will terminate your application.
//
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
if (!Resolver.IsSet) SetIoc();
global::Xamarin.Forms.Forms.Init();
SvgImageRenderer.Init ();
LoadApplication(new App());
return base.FinishedLaunching(app, options);
}
public override bool OpenUrl (UIApplication app, NSUrl url, string sourceApp, NSObject annotation)
{
var resetLinkHash = string.Empty;
if (url.BaseUrl.Host.Equals ("app.myapp.io")) {
if (!Resolver.IsSet) SetIoc();
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App(url.LastPathComponent));
return true;
}
LoadApplication(new App(url.LastPathComponent));
return true;
}
private void SetIoc()
{
TinyIoCContainer.Current.AutoRegister ();
var container = TinyIoCContainer.Current;
container.Register<IDeviceStorage>(this);
container.Register<IXFormsApp> (new XFormsAppiOS ());
container.Register<ISecureStorage, SecureStorage> ();
Resolver.SetResolver(new XLabs.Ioc.TinyIOC.TinyResolver(container));
}
}
}
这是我的 Main.cs
{
public class Application
{
// This is the main entry point of the application.
static void Main(string[] args)
{
// if you want to use a different Application Delegate class from "AppDelegate"
// you can specify it here.
UIApplication.Main(args, null, "AppDelegate");
}
}
}
好吧,现在这在 iOS 上不起作用,请尝试在开始时使用或不使用 http。
如果有人能指出正确的方向,我将不胜感激。通过匹配 url 来启动应用程序对我来说非常重要,做一些像向页面 html 添加一些 <meta/>
标签这样的事情将不起作用,因为我没有任何服务器访问权限.
与 Android 不同,iOS 上的 URL 方案只能注册到单个应用程序。这对您不起作用的原因是因为 http
不是可用的 URL 方案,您的应用程序可以自行注册以在 iOS.
上使用
实现此功能的方法是 Universal Links, which is a new iOS 9+ feature. This allows you to register your app for http/https URLs on a specific domain only. However, you'll need access to the server for this, because you need to make some server-side changes to prove that you control the domain in question. If this is impossible, consider using a free service like Branch.io(完全披露:我是团队成员)来处理您的链接。
我正在为 Android 和 iOS 使用 Xamarin.Forms 开发一个应用程序。当我输入类似于 http://app.myapp.io/user/reset-password/{some_hash}
的 url 时,我会在一个特殊屏幕中打开该应用程序,该屏幕允许用户为其帐户设置新密码。
在 Android 中,我通过使用自定义意图过滤器实现了这一点,将方案设置为 http
并将主机设置为 app.myapp.io
。我想在 iOS 中做同样的事情。但是据我所知,当您在 iOS 中注册应用程序链接时,方法是在您的 Info.plist
文件中注册自定义方案。这是我 Info.plist
文件中的自定义方案。
<?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>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>MinimumOSVersion</key>
<string>6.0</string>
<key>CFBundleDisplayName</key>
<string>MyApp</string>
<key>CFBundleIdentifier</key>
<string>com.company.app</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>CFBundleIconFiles</key>
<array>
<string>Icon-60@2x</string>
<string>Icon-60@3x</string>
<string>Icon-76</string>
<string>Icon-76@2x</string>
<string>Default</string>
<string>Default@2x</string>
<string>Default-568h@2x</string>
<string>Default-Portrait</string>
<string>Default-Portrait@2x</string>
<string>Icon-Small-40</string>
<string>Icon-Small-40@2x</string>
<string>Icon-Small-40@3x</string>
<string>Icon-Small</string>
<string>Icon-Small@2x</string>
<string>Icon-Small@3x</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>CFBundleName</key>
<string>Halligan</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>com.company.app</string>
<key>CFBundleURLSchemes</key>
<array>
<string>http</string>
</array>
</dict>
</array>
</dict>
</plist>
这是我的 AppDelegate.cs
{
// The UIApplicationDelegate for the application. This class is responsible for launching the
// User Interface of the application, as well as listening (and optionally responding) to
// application events from iOS.
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate, IDeviceStorage
{
const string HOCKEYAPP_APPID = "ef71d53e56044baa813c2381b291c355";
#region IDeviceStorage implementation
public string LoadString(string key, string def = null)
{
string value = NSUserDefaults.StandardUserDefaults.StringForKey(key);
if (value == null)
return def;
else
return value;
}
public void SaveString(string key, string value)
{
NSUserDefaults.StandardUserDefaults.SetString(value, key);
NSUserDefaults.StandardUserDefaults.Synchronize();
}
#endregion
//
// This method is invoked when the application has loaded and is ready to run. In this
// method you should instantiate the window, load the UI into it and then make the window
// visible.
//
// You have 17 seconds to return from this method, or iOS will terminate your application.
//
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
if (!Resolver.IsSet) SetIoc();
global::Xamarin.Forms.Forms.Init();
SvgImageRenderer.Init ();
LoadApplication(new App());
return base.FinishedLaunching(app, options);
}
public override bool OpenUrl (UIApplication app, NSUrl url, string sourceApp, NSObject annotation)
{
var resetLinkHash = string.Empty;
if (url.BaseUrl.Host.Equals ("app.myapp.io")) {
if (!Resolver.IsSet) SetIoc();
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App(url.LastPathComponent));
return true;
}
LoadApplication(new App(url.LastPathComponent));
return true;
}
private void SetIoc()
{
TinyIoCContainer.Current.AutoRegister ();
var container = TinyIoCContainer.Current;
container.Register<IDeviceStorage>(this);
container.Register<IXFormsApp> (new XFormsAppiOS ());
container.Register<ISecureStorage, SecureStorage> ();
Resolver.SetResolver(new XLabs.Ioc.TinyIOC.TinyResolver(container));
}
}
}
这是我的 Main.cs
{
public class Application
{
// This is the main entry point of the application.
static void Main(string[] args)
{
// if you want to use a different Application Delegate class from "AppDelegate"
// you can specify it here.
UIApplication.Main(args, null, "AppDelegate");
}
}
}
好吧,现在这在 iOS 上不起作用,请尝试在开始时使用或不使用 http。
如果有人能指出正确的方向,我将不胜感激。通过匹配 url 来启动应用程序对我来说非常重要,做一些像向页面 html 添加一些 <meta/>
标签这样的事情将不起作用,因为我没有任何服务器访问权限.
与 Android 不同,iOS 上的 URL 方案只能注册到单个应用程序。这对您不起作用的原因是因为 http
不是可用的 URL 方案,您的应用程序可以自行注册以在 iOS.
实现此功能的方法是 Universal Links, which is a new iOS 9+ feature. This allows you to register your app for http/https URLs on a specific domain only. However, you'll need access to the server for this, because you need to make some server-side changes to prove that you control the domain in question. If this is impossible, consider using a free service like Branch.io(完全披露:我是团队成员)来处理您的链接。