From 66892d1bc7567bd578c9acf4de7cad09d820eb88 Mon Sep 17 00:00:00 2001 From: Sarah Zakarias Date: Thu, 27 Apr 2017 21:48:24 +0200 Subject: [PATCH] Add canLaunch method to url_launcher plugin (#8) --- packages/url-launcher/CHANGELOG.md | 3 + .../url_launcher/UrlLauncherPlugin.java | 72 ++++++++----- .../ios/Pods/Pods.xcodeproj/project.pbxproj | 102 +++++++++--------- .../Pods-Runner/Pods-Runner-frameworks.sh | 4 +- .../Pods-Runner/Pods-Runner.debug.xcconfig | 2 +- .../Pods-Runner/Pods-Runner.release.xcconfig | 2 +- packages/url-launcher/example/lib/main.dart | 56 +++++++--- .../ios/Classes/UrlLauncherPlugin.m | 44 ++++++-- packages/url-launcher/lib/url_launcher.dart | 17 ++- packages/url-launcher/pubspec.yaml | 2 +- 10 files changed, 198 insertions(+), 106 deletions(-) diff --git a/packages/url-launcher/CHANGELOG.md b/packages/url-launcher/CHANGELOG.md index 2cb5ffed5340..4c98b259cf8f 100644 --- a/packages/url-launcher/CHANGELOG.md +++ b/packages/url-launcher/CHANGELOG.md @@ -1,3 +1,6 @@ +## [0.3.0] - 2017-04-27 + +* Add `canLaunch` method. ## [0.2.0] - 2017-04-24 diff --git a/packages/url-launcher/android/src/main/java/io/flutter/plugins/url_launcher/UrlLauncherPlugin.java b/packages/url-launcher/android/src/main/java/io/flutter/plugins/url_launcher/UrlLauncherPlugin.java index c20f7e75c3d4..347a6f68af33 100644 --- a/packages/url-launcher/android/src/main/java/io/flutter/plugins/url_launcher/UrlLauncherPlugin.java +++ b/packages/url-launcher/android/src/main/java/io/flutter/plugins/url_launcher/UrlLauncherPlugin.java @@ -1,5 +1,10 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + package io.flutter.plugins.url_launcher; +import android.content.ComponentName; import android.content.Intent; import android.net.Uri; @@ -13,34 +18,45 @@ * UrlLauncherPlugin */ public class UrlLauncherPlugin implements MethodCallHandler { - private FlutterActivity activity; - - public static UrlLauncherPlugin register(FlutterActivity activity) { - return new UrlLauncherPlugin(activity); - } - - private UrlLauncherPlugin(FlutterActivity activity) { - this.activity = activity; - new MethodChannel( - activity.getFlutterView(), "plugins.flutter.io/URLLauncher").setMethodCallHandler(this); - } - - @Override - public void onMethodCall(MethodCall call, Result result) { - if (call.method.equals("UrlLauncher.launch")) { - launchURL((String) call.arguments); - result.success(null); - } else { - result.notImplemented(); + private FlutterActivity activity; + + public static UrlLauncherPlugin register(FlutterActivity activity) { + return new UrlLauncherPlugin(activity); + } + + private UrlLauncherPlugin(FlutterActivity activity) { + this.activity = activity; + new MethodChannel( + activity.getFlutterView(), "plugins.flutter.io/url_launcher").setMethodCallHandler(this); + } + + @Override + public void onMethodCall(MethodCall call, Result result) { + String url = call.arguments(); + if (call.method.equals("canLaunch")) { + canLaunch(url, result); + } else if (call.method.equals("launch")) { + launchURL(url, result); + } else { + result.notImplemented(); + } + } + + private void launchURL(String url, Result result) { + Intent launchIntent = new Intent(Intent.ACTION_VIEW); + launchIntent.setData(Uri.parse(url)); + activity.startActivity(launchIntent); + result.success(null); } - } - private void launchURL(String url) { - try { - Intent launchIntent = new Intent(Intent.ACTION_VIEW); - launchIntent.setData(Uri.parse(url)); - activity.startActivity(launchIntent); - } catch (java.lang.Exception exception) { - // Ignore parsing or ActivityNotFound errors + + private void canLaunch(String url, Result result) { + Intent launchIntent = new Intent(Intent.ACTION_VIEW); + launchIntent.setData(Uri.parse(url)); + ComponentName componentName = launchIntent.resolveActivity(activity.getPackageManager()); + + boolean canLaunch = componentName != null && + !"{com.android.fallback/com.android.fallback.Fallback}". + equals(componentName.toShortString()); + result.success(canLaunch); } - } } diff --git a/packages/url-launcher/example/ios/Pods/Pods.xcodeproj/project.pbxproj b/packages/url-launcher/example/ios/Pods/Pods.xcodeproj/project.pbxproj index d3b2f6e47881..b703a6beec2d 100644 --- a/packages/url-launcher/example/ios/Pods/Pods.xcodeproj/project.pbxproj +++ b/packages/url-launcher/example/ios/Pods/Pods.xcodeproj/project.pbxproj @@ -7,14 +7,14 @@ objects = { /* Begin PBXBuildFile section */ - 0E483423E9DCAEA9851A77F4678074A9 /* UrlLauncherPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C18D72EA8BAB1FC3C0FCE584E0A310E /* UrlLauncherPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0E483423E9DCAEA9851A77F4678074A9 /* UrlLauncherPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = DBB19A6417A00E2709A4CC67BC499435 /* UrlLauncherPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1B0ACC20E310CA80EFB60BF34C9B4184 /* Pods-Runner-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E631AC9676BE84AEB52F7D6520E4684 /* Pods-Runner-dummy.m */; }; 4415323DEF18C14449AA182F7811169E /* Pods-Runner-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 800A16960E73EBAF012C139238277358 /* Pods-Runner-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 568F29DDF606A6C38F8DF8EED181E02A /* url_launcher-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = B241FCE379E0E69CF112BE404067F65C /* url_launcher-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 568F29DDF606A6C38F8DF8EED181E02A /* url_launcher-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = D33EE0AFDF865FC57DE4AFE8D4A1FE2D /* url_launcher-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 74DD29F300E0CBE5C7ECCD118B18AFF1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CBB3DE36805AF21409EC968A9691732F /* Foundation.framework */; }; 7C942C0895A8904C17777BD7F7929526 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CBB3DE36805AF21409EC968A9691732F /* Foundation.framework */; }; - B675652788D552B0B818758E03B07B16 /* UrlLauncherPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D3BACBA6F7E36892A1B6492CB55DEB5 /* UrlLauncherPlugin.m */; }; - EE31ED9F7764675F7D27B13E08EE4351 /* url_launcher-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = EC54CA739E4C29E530C11E341B837700 /* url_launcher-dummy.m */; }; + B675652788D552B0B818758E03B07B16 /* UrlLauncherPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A5EC4C1C7345C1568EA4391116B5FA5 /* UrlLauncherPlugin.m */; }; + EE31ED9F7764675F7D27B13E08EE4351 /* url_launcher-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 93FBA44B61BC2932F585020591D983DE /* url_launcher-dummy.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -29,28 +29,28 @@ /* Begin PBXFileReference section */ 09472E02B60DD42496A3E3B59C6F14B6 /* url_launcher.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = url_launcher.framework; path = url_launcher.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 0D3BACBA6F7E36892A1B6492CB55DEB5 /* UrlLauncherPlugin.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = UrlLauncherPlugin.m; sourceTree = ""; }; 1230911B0B1C1A5E00676A90606DE300 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 1E631AC9676BE84AEB52F7D6520E4684 /* Pods-Runner-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-Runner-dummy.m"; sourceTree = ""; }; - 34E1DEDD52719A2742E34C53D93CB0D9 /* url_launcher-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "url_launcher-prefix.pch"; sourceTree = ""; }; + 31988D6AAEEC615DF7F8C1AA0A95CC28 /* url_launcher.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = url_launcher.modulemap; sourceTree = ""; }; + 3A5EC4C1C7345C1568EA4391116B5FA5 /* UrlLauncherPlugin.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = UrlLauncherPlugin.m; sourceTree = ""; }; 48E25B5D7653FD9F13A9662BB6AF2D86 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_Runner.framework; path = "Pods-Runner.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C18D72EA8BAB1FC3C0FCE584E0A310E /* UrlLauncherPlugin.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = UrlLauncherPlugin.h; sourceTree = ""; }; - 4F8BCA982F22D010C0F3751AAC7E3C1B /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 4FDED4BA7D4F5DF30B2103FF868343B2 /* url_launcher.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = url_launcher.xcconfig; sourceTree = ""; }; + 537A6898C89F37EC7BE5BF570CDE5529 /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Flutter.framework; sourceTree = ""; }; 5EB571A3ABC7BF67A4642C216D6F0E21 /* Pods-Runner-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-Runner-resources.sh"; sourceTree = ""; }; 60BA499A645871628CFA2E5806E78269 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Runner.release.xcconfig"; sourceTree = ""; }; 63BC99522783D0218755FDE8464650E4 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Runner.debug.xcconfig"; sourceTree = ""; }; - 6C259E7AAD6CFE65A1929C7AE2F2149C /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Flutter.framework; sourceTree = ""; }; - 7FE36E7B286DF735A45138EED907BD05 /* url_launcher.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = url_launcher.modulemap; sourceTree = ""; }; 800A16960E73EBAF012C139238277358 /* Pods-Runner-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-Runner-umbrella.h"; sourceTree = ""; }; 820303DDBFB04D47450E66B28FF32086 /* Pods-Runner-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Runner-acknowledgements.plist"; sourceTree = ""; }; + 8629EEB906A7D06D81A6ED5F5D9991FF /* url_launcher-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "url_launcher-prefix.pch"; sourceTree = ""; }; 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - B241FCE379E0E69CF112BE404067F65C /* url_launcher-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "url_launcher-umbrella.h"; sourceTree = ""; }; + 93FBA44B61BC2932F585020591D983DE /* url_launcher-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "url_launcher-dummy.m"; sourceTree = ""; }; B8331DA3DF79C3AB28033920E45C4B46 /* Pods-Runner-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-Runner-frameworks.sh"; sourceTree = ""; }; + B8CE98FF8B1978EDB8B54B7B3FE5E630 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; BE191574A51A7A7D07FEEACB1323F4E5 /* Pods-Runner.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = "Pods-Runner.modulemap"; sourceTree = ""; }; CA0501A66E945611274FD9BED1573FA5 /* Pods-Runner-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-Runner-acknowledgements.markdown"; sourceTree = ""; }; CBB3DE36805AF21409EC968A9691732F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - EC54CA739E4C29E530C11E341B837700 /* url_launcher-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "url_launcher-dummy.m"; sourceTree = ""; }; - FF074A713E045420CE534C44F0714398 /* url_launcher.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = url_launcher.xcconfig; sourceTree = ""; }; + D33EE0AFDF865FC57DE4AFE8D4A1FE2D /* url_launcher-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "url_launcher-umbrella.h"; sourceTree = ""; }; + DBB19A6417A00E2709A4CC67BC499435 /* UrlLauncherPlugin.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = UrlLauncherPlugin.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -73,70 +73,80 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 2CA9FE3F5F1970ED10865F8F8F801B37 /* Development Pods */ = { + 18070631AF21DF6AF05EF8800C08C3B4 /* Frameworks */ = { isa = PBXGroup; children = ( - 9EA7DAF2ABC963E27C71D95155AA6383 /* Flutter */, - C9845581E162B3675B72C928ECAD12E2 /* url_launcher */, + 537A6898C89F37EC7BE5BF570CDE5529 /* Flutter.framework */, ); - name = "Development Pods"; + name = Frameworks; sourceTree = ""; }; - 2CBBD2BBAF933B29A5485E559E24299A /* Classes */ = { + 7531C8F8DE19F1AA3C8A7AC97A91DC29 /* iOS */ = { isa = PBXGroup; children = ( - 4C18D72EA8BAB1FC3C0FCE584E0A310E /* UrlLauncherPlugin.h */, - 0D3BACBA6F7E36892A1B6492CB55DEB5 /* UrlLauncherPlugin.m */, + CBB3DE36805AF21409EC968A9691732F /* Foundation.framework */, ); - name = Classes; - path = Classes; + name = iOS; sourceTree = ""; }; - 7531C8F8DE19F1AA3C8A7AC97A91DC29 /* iOS */ = { + 7D45BA6CBE8EEF5E46C6761CCDF60B06 /* Development Pods */ = { isa = PBXGroup; children = ( - CBB3DE36805AF21409EC968A9691732F /* Foundation.framework */, + A8AD025A0715AA1BCA1BE8CAC29A029B /* Flutter */, + 8A8F602384D136C1024D2774B770BC21 /* url_launcher */, ); - name = iOS; + name = "Development Pods"; sourceTree = ""; }; 7DB346D0F39D3F0E887471402A8071AB = { isa = PBXGroup; children = ( 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, - 2CA9FE3F5F1970ED10865F8F8F801B37 /* Development Pods */, + 7D45BA6CBE8EEF5E46C6761CCDF60B06 /* Development Pods */, BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */, F20E12BEB87796FA91406DA2EEDF8F75 /* Products */, B88D6092221BFC46BA797811AC7C0DEC /* Targets Support Files */, ); sourceTree = ""; }; - 99ACA14533349144112BBA3BBFE4912C /* Frameworks */ = { + 8A8F602384D136C1024D2774B770BC21 /* url_launcher */ = { isa = PBXGroup; children = ( - 6C259E7AAD6CFE65A1929C7AE2F2149C /* Flutter.framework */, + 8D07D777E9B2A0CBE17035732DB3A141 /* Classes */, + AF12D087686A3EFD85941828E0BCC355 /* Support Files */, ); - name = Frameworks; + name = url_launcher; + path = "/Users/zarah/plugins/packages/url-launcher/ios"; + sourceTree = ""; + }; + 8D07D777E9B2A0CBE17035732DB3A141 /* Classes */ = { + isa = PBXGroup; + children = ( + DBB19A6417A00E2709A4CC67BC499435 /* UrlLauncherPlugin.h */, + 3A5EC4C1C7345C1568EA4391116B5FA5 /* UrlLauncherPlugin.m */, + ); + name = Classes; + path = Classes; sourceTree = ""; }; - 9EA7DAF2ABC963E27C71D95155AA6383 /* Flutter */ = { + A8AD025A0715AA1BCA1BE8CAC29A029B /* Flutter */ = { isa = PBXGroup; children = ( - 99ACA14533349144112BBA3BBFE4912C /* Frameworks */, + 18070631AF21DF6AF05EF8800C08C3B4 /* Frameworks */, ); name = Flutter; - path = "/Users/zarah/flutter/bin/cache/artifacts/engine/ios-release"; + path = /Users/zarah/flutter/bin/cache/artifacts/engine/ios; sourceTree = ""; }; - ACF591A9AAFFE9A5DEEAD4CD4EC5352D /* Support Files */ = { + AF12D087686A3EFD85941828E0BCC355 /* Support Files */ = { isa = PBXGroup; children = ( - 4F8BCA982F22D010C0F3751AAC7E3C1B /* Info.plist */, - 7FE36E7B286DF735A45138EED907BD05 /* url_launcher.modulemap */, - FF074A713E045420CE534C44F0714398 /* url_launcher.xcconfig */, - EC54CA739E4C29E530C11E341B837700 /* url_launcher-dummy.m */, - 34E1DEDD52719A2742E34C53D93CB0D9 /* url_launcher-prefix.pch */, - B241FCE379E0E69CF112BE404067F65C /* url_launcher-umbrella.h */, + B8CE98FF8B1978EDB8B54B7B3FE5E630 /* Info.plist */, + 31988D6AAEEC615DF7F8C1AA0A95CC28 /* url_launcher.modulemap */, + 4FDED4BA7D4F5DF30B2103FF868343B2 /* url_launcher.xcconfig */, + 93FBA44B61BC2932F585020591D983DE /* url_launcher-dummy.m */, + 8629EEB906A7D06D81A6ED5F5D9991FF /* url_launcher-prefix.pch */, + D33EE0AFDF865FC57DE4AFE8D4A1FE2D /* url_launcher-umbrella.h */, ); name = "Support Files"; path = "../example/ios/Pods/Target Support Files/url_launcher"; @@ -158,16 +168,6 @@ name = Frameworks; sourceTree = ""; }; - C9845581E162B3675B72C928ECAD12E2 /* url_launcher */ = { - isa = PBXGroup; - children = ( - 2CBBD2BBAF933B29A5485E559E24299A /* Classes */, - ACF591A9AAFFE9A5DEEAD4CD4EC5352D /* Support Files */, - ); - name = url_launcher; - path = "/Users/zarah/plugins/packages/url-launcher/ios"; - sourceTree = ""; - }; ECC1486D1F14EC5BA692C079D9D06161 /* Pods-Runner */ = { isa = PBXGroup; children = ( @@ -433,7 +433,7 @@ }; 66B9050C99E4D2D621D4C7E6F1944502 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = FF074A713E045420CE534C44F0714398 /* url_launcher.xcconfig */; + baseConfigurationReference = 4FDED4BA7D4F5DF30B2103FF868343B2 /* url_launcher.xcconfig */; buildSettings = { ARCHS = arm64; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -503,7 +503,7 @@ }; D5E30FCB1F1B03C78FBACDDD90DBAD54 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = FF074A713E045420CE534C44F0714398 /* url_launcher.xcconfig */; + baseConfigurationReference = 4FDED4BA7D4F5DF30B2103FF868343B2 /* url_launcher.xcconfig */; buildSettings = { ARCHS = arm64; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; diff --git a/packages/url-launcher/example/ios/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh b/packages/url-launcher/example/ios/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh index ca7c17060c95..84e33cb7b6e8 100755 --- a/packages/url-launcher/example/ios/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh +++ b/packages/url-launcher/example/ios/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh @@ -89,11 +89,11 @@ strip_invalid_archs() { if [[ "$CONFIGURATION" == "Debug" ]]; then - install_framework "${PODS_ROOT}/../../../../../../flutter/bin/cache/artifacts/engine/ios-release/Flutter.framework" + install_framework "${PODS_ROOT}/../../../../../../flutter/bin/cache/artifacts/engine/ios/Flutter.framework" install_framework "$BUILT_PRODUCTS_DIR/url_launcher/url_launcher.framework" fi if [[ "$CONFIGURATION" == "Release" ]]; then - install_framework "${PODS_ROOT}/../../../../../../flutter/bin/cache/artifacts/engine/ios-release/Flutter.framework" + install_framework "${PODS_ROOT}/../../../../../../flutter/bin/cache/artifacts/engine/ios/Flutter.framework" install_framework "$BUILT_PRODUCTS_DIR/url_launcher/url_launcher.framework" fi if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then diff --git a/packages/url-launcher/example/ios/Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig b/packages/url-launcher/example/ios/Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig index 81ffb4884db2..283f6a71cf3a 100644 --- a/packages/url-launcher/example/ios/Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig +++ b/packages/url-launcher/example/ios/Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig @@ -1,4 +1,4 @@ -FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/url_launcher" "${PODS_ROOT}/../../../../../../flutter/bin/cache/artifacts/engine/ios-release" +FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/url_launcher" "${PODS_ROOT}/../../../../../../flutter/bin/cache/artifacts/engine/ios" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Flutter" LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' diff --git a/packages/url-launcher/example/ios/Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig b/packages/url-launcher/example/ios/Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig index 81ffb4884db2..283f6a71cf3a 100644 --- a/packages/url-launcher/example/ios/Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig +++ b/packages/url-launcher/example/ios/Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig @@ -1,4 +1,4 @@ -FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/url_launcher" "${PODS_ROOT}/../../../../../../flutter/bin/cache/artifacts/engine/ios-release" +FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/url_launcher" "${PODS_ROOT}/../../../../../../flutter/bin/cache/artifacts/engine/ios" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Flutter" LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' diff --git a/packages/url-launcher/example/lib/main.dart b/packages/url-launcher/example/lib/main.dart index 86018261b4ac..c98b7fd6bb7a 100644 --- a/packages/url-launcher/example/lib/main.dart +++ b/packages/url-launcher/example/lib/main.dart @@ -1,3 +1,9 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -9,7 +15,7 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp( - title: 'URL Laucher', + title: 'URL Launcher', theme: new ThemeData( primarySwatch: Colors.blue, ), @@ -27,8 +33,28 @@ class MyHomePage extends StatefulWidget { } class _MyHomePageState extends State { + Future _launched; + void _launchUrl() { - launch('https://flutter.io'); + setState(() { + _launched = _launch('https://flutter.io'); + }); + } + + Future _launch(String url) async { + if (await canLaunch(url)) { + await launch(url); + } else { + throw "Could not launch $url"; + } + } + + Widget _launchStatus(BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.hasError) { + return new Text('Error: ${snapshot.error}'); + } else { + return const Text(''); + } } @override @@ -38,17 +64,23 @@ class _MyHomePageState extends State { title: new Text(widget.title), ), body: new Center( - child: new Row( - mainAxisSize: MainAxisSize.min, - children: [ - new Padding( - padding: new EdgeInsets.all(16.0), - child: new Text("https://flutter.io"), - ), - new RaisedButton( - onPressed: _launchUrl, - child: new Text("Go"), + child: new Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + new Row( + mainAxisSize: MainAxisSize.min, + children: [ + new Padding( + padding: new EdgeInsets.all(16.0), + child: new Text("https://flutter.io"), + ), + new RaisedButton( + onPressed: _launchUrl, + child: new Text("Go"), + ), + ], ), + new FutureBuilder(future: _launched, builder: _launchStatus), ], ), ), diff --git a/packages/url-launcher/ios/Classes/UrlLauncherPlugin.m b/packages/url-launcher/ios/Classes/UrlLauncherPlugin.m index ea4d43a10d46..1b31ddb08328 100644 --- a/packages/url-launcher/ios/Classes/UrlLauncherPlugin.m +++ b/packages/url-launcher/ios/Classes/UrlLauncherPlugin.m @@ -3,28 +3,56 @@ @implementation UrlLauncherPlugin { } -- (instancetype)initWithController:(FlutterViewController *)controller { +- (instancetype)initWithController:(FlutterViewController*)controller { self = [super init]; if (self) { FlutterMethodChannel* channel = [FlutterMethodChannel - methodChannelWithName:@"plugins.flutter.io/URLLauncher" + methodChannelWithName:@"plugins.flutter.io/url_launcher" binaryMessenger:controller]; [channel setMethodCallHandler:^(FlutterMethodCall *call, FlutterResult result) { - if ([@"UrlLauncher.launch" isEqualToString:call.method]) { - [self launchURL:call.arguments]; - result(nil); + NSString* url = call.arguments; + if ([@"canLaunch" isEqualToString:call.method]) { + result(@([self canLaunchURL:url])); + } else if ([@"launch" isEqualToString:call.method]) { + [self launchURL:url result:result]; + } else { + result(FlutterMethodNotImplemented); } }]; } return self; } -- (NSDictionary*)launchURL:(NSString*)urlString { +- (BOOL)canLaunchURL:(NSString*)urlString { NSURL* url = [NSURL URLWithString:urlString]; UIApplication* application = [UIApplication sharedApplication]; - bool success = [application canOpenURL:url] && [application openURL:url]; - return @{@"success": @(success) }; + return [application canOpenURL:url]; +} + +- (void)launchURL:(NSString*)urlString result:(FlutterResult)result { + NSURL* url = [NSURL URLWithString:urlString]; + UIApplication* application = [UIApplication sharedApplication]; + if ([application respondsToSelector:@selector(openURL:options:completionHandler:)]) { + // iOS 10 and above + [application openURL:url options:@{} completionHandler: ^(BOOL success) { + [self sendResult:success result:result url:url]; + }]; + } else { + [self sendResult:[application openURL:url] result:result url:url]; + } +} + +- (void)sendResult:(BOOL)success result:(FlutterResult)result url:(NSURL*)url { + if (success) { + result(nil); + } else { + result([FlutterError errorWithCode:@"Error" + message:[NSString stringWithFormat:@"Error while launching %@", url] + details:nil]); + + } + } @end diff --git a/packages/url-launcher/lib/url_launcher.dart b/packages/url-launcher/lib/url_launcher.dart index cef7d7a82a2d..999ee0c28a87 100644 --- a/packages/url-launcher/lib/url_launcher.dart +++ b/packages/url-launcher/lib/url_launcher.dart @@ -1,12 +1,25 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import 'dart:async'; import 'package:flutter/services.dart'; +const _channel = const MethodChannel('plugins.flutter.io/url_launcher'); + /// Parse the specified URL string and delegate handling of the same to the /// underlying platform. Future launch(String urlString) { - return const MethodChannel('plugins.flutter.io/URLLauncher').invokeMethod( - 'UrlLauncher.launch', + return _channel.invokeMethod( + 'launch', + urlString, + ); +} + +Future canLaunch(String urlString) { + return _channel.invokeMethod( + 'canLaunch', urlString, ); } diff --git a/packages/url-launcher/pubspec.yaml b/packages/url-launcher/pubspec.yaml index 083cd90ac3b3..92e2c458e01a 100644 --- a/packages/url-launcher/pubspec.yaml +++ b/packages/url-launcher/pubspec.yaml @@ -1,6 +1,6 @@ name: url_launcher -version: 0.2.0 +version: 0.3.0 description: Flutter plugin for launching a URL author: Flutter Team homepage: https://github.com/flutter/plugins