Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

[url_launcher] Update README to use code excerpts. #6042

Merged
merged 10 commits into from
Jul 13, 2022
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/url_launcher/url_launcher/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 6.1.5

* Migrates `README.md` examples to the [`code-excerpt` system](https://github.com/flutter/flutter/wiki/Contributing-to-Plugins-and-Packages#readme-code).

## 6.1.4

* Adopts new platform interface method for launching URLs.
Expand Down
68 changes: 49 additions & 19 deletions packages/url_launcher/url_launcher/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<?code-excerpt path-base="excerpts/packages/url_launcher_example"?>

# url_launcher

[![pub package](https://img.shields.io/pub/v/url_launcher.svg)](https://pub.dev/packages/url_launcher)
Expand All @@ -14,6 +16,7 @@ To use this plugin, add `url_launcher` as a [dependency in your pubspec.yaml fil

### Example

<?code-excerpt "basic.dart (basic-example)"?>
``` dart
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
Expand All @@ -24,7 +27,7 @@ void main() => runApp(
const MaterialApp(
home: Material(
child: Center(
child: RaisedButton(
child: ElevatedButton(
onPressed: _launchUrl,
child: Text('Show Flutter homepage'),
),
Expand All @@ -33,8 +36,10 @@ void main() => runApp(
),
);

void _launchUrl() async {
if (!await launchUrl(_url)) throw 'Could not launch $_url';
Future<void> _launchUrl() async {
if (!await launchUrl(_url)) {
throw 'Could not launch $_url';
}
}
```

Expand Down Expand Up @@ -65,18 +70,25 @@ on Android 11 (API 30) or higher. A `<queries>`
element must be added to your manifest as a child of the root element.

Example:

<?code-excerpt "../../android/app/src/main/AndroidManifest.xml (android-queries)"?>
``` xml
<!-- Provide required visibility configuration for API level 30 and above -->
<queries>
<!-- If your app checks for SMS support -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="sms" />
<data android:scheme="https" />
Copy link
Contributor

Choose a reason for hiding this comment

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

We should excerpt the https block out (by making it a non-contiguous region); https is in the example because it's thing we can use in integration tests on any device that should return true, but there's basically no reason any actual app should need to check for it (for the same reason). I actually recently removed this from the README example.

Copy link
Member

Choose a reason for hiding this comment

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

Done, I've removed the https block from the docregion, and used an empty "plaster" so it doesn't even shows up as "..." in the docs.

</intent>
<!-- If your app checks for call support -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="tel" />
</intent>
<!-- If your app checks for SMS support -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="sms" />
</intent>
</queries>
```

Expand Down Expand Up @@ -133,22 +145,37 @@ due to [a bug](https://github.com/dart-lang/sdk/issues/43838) in the way `Uri`
encodes query parameters. Using `queryParameters` will result in spaces being
converted to `+` in many cases.

<?code-excerpt "encoding.dart (encode-query-parameters)"?>
```dart
String? encodeQueryParameters(Map<String, String> params) {
return params.entries
.map((e) => '${Uri.encodeComponent(e.key)}=${Uri.encodeComponent(e.value)}')
.map((MapEntry<String, String> e) =>
'${Uri.encodeComponent(e.key)}=${Uri.encodeComponent(e.value)}')
.join('&');
}
// ···
final Uri emailLaunchUri = Uri(
scheme: 'mailto',
path: '[email protected]',
query: encodeQueryParameters(<String, String>{
'subject': 'Example Subject & Symbols are allowed!',
}),
);

launchUrl(emailLaunchUri);
```

final Uri emailLaunchUri = Uri(
scheme: 'mailto',
path: '[email protected]',
query: encodeQueryParameters(<String, String>{
'subject': 'Example Subject & Symbols are allowed!'
}),
);
Encoding for `sms` is slightly different:

launchUrl(emailLaunchUri);
<?code-excerpt "encoding.dart (sms)"?>
```dart
final Uri smsLaunchUri = Uri(
scheme: 'sms',
path: '0118 999 881 999 119 7253',
Copy link
Contributor

Choose a reason for hiding this comment

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

🤣

I was about to ask why this wasn't using some obviously fake number (like 123456789) when I realized what it was 🙂

Copy link
Member

Choose a reason for hiding this comment

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

I tried to find a cool "555" number, but ended up going for the easy to remember 0118 999 881 999 119 725... 3

(Turns out I'm almost 7 years late, yikes!)

queryParameters: <String, String>{
'body': Uri.encodeComponent('Example Subject & Symbols are allowed!'),
},
);
```

### URLs not handled by `Uri`
Expand All @@ -168,14 +195,17 @@ original APIs.
We recommend checking first whether the directory or file exists before calling `launchUrl`.

Example:

<?code-excerpt "files.dart (file)"?>
```dart
var filePath = '/path/to/file';
final String filePath = testFile.absolute.path;
final Uri uri = Uri.file(filePath);

if (await File(uri.toFilePath()).exists()) {
if (!await launchUrl(uri)) {
throw 'Could not launch $uri';
}
if (!File(uri.toFilePath()).existsSync() || !await canLaunchUrl(uri)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We've moved pretty strongly away from recommending canLaunchUrl before launchUrl since it most cases—as here—it's actually useless. I'm fine with this new structure, but the second condition should be removed.

Copy link
Member

Choose a reason for hiding this comment

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

Removed the call to canLaunchUrl, and the note about not having a registered handler.

throw "$uri does not exist, or there's no handler registered for it!";
}
if (!await launchUrl(uri)) {
throw 'Could not launch $uri';
}
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,25 @@
-->
<uses-permission android:name="android.permission.INTERNET"/>

<!--#docregion android-queries-->
<!-- Provide required visibility configuration for API level 30 and above -->
<queries>
<intent>
Copy link
Contributor

Choose a reason for hiding this comment

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

It's probably worth adding a comment saying this is only here for integration tests, and shouldn't be needed in most actual apps, so it doesn't confuse anyone else in the future.

Copy link
Member

Choose a reason for hiding this comment

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

Agreed; I've added a comment to the https scheme bit of the XML, in addition to excluding it from the relevant docregion.

<action android:name="android.intent.action.VIEW" />
<data android:scheme="https" />
</intent>
<!-- If your app checks for call support -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="tel" />
</intent>
<!-- If your app checks for SMS support -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="sms" />
</intent>
</queries>
<!--#enddocregion android-queries-->

<application
android:icon="@mipmap/ic_launcher"
Expand Down
20 changes: 20 additions & 0 deletions packages/url_launcher/url_launcher/example/build.excerpt.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
targets:
$default:
sources:
include:
- lib/**
- android/app/src/main/**
# Some default includes that aren't really used here but will prevent
# false-negative warnings:
- $package$
- lib/$lib$
exclude:
- '**/.*/**'
- '**/build/**'
- 'android/app/src/main/res/**'
builders:
code_excerpter|code_excerpter:
enabled: true
generate_for:
- '**/*.dart'
- android/**/*.xml
34 changes: 34 additions & 0 deletions packages/url_launcher/url_launcher/example/lib/basic.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Run this example with: flutter run -t lib/basic.dart -d emulator

// This file is used to extract code samples for the README.md file.
// Run update-excerpts if you modify this file.

// #docregion basic-example
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';

final Uri _url = Uri.parse('https://flutter.dev');

void main() => runApp(
const MaterialApp(
home: Material(
child: Center(
child: ElevatedButton(
onPressed: _launchUrl,
child: Text('Show Flutter homepage'),
),
),
),
),
);

Future<void> _launchUrl() async {
if (!await launchUrl(_url)) {
throw 'Could not launch $_url';
}
}
// #enddocregion basic-example
70 changes: 70 additions & 0 deletions packages/url_launcher/url_launcher/example/lib/encoding.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Run this example with: flutter run -t lib/encoding.dart -d emulator

// This file is used to extract code samples for the README.md file.
// Run update-excerpts if you modify this file.

import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';

/// Encode [params] so it produces a correct query string.
/// Workaround for: https://github.com/dart-lang/sdk/issues/43838
// #docregion encode-query-parameters
String? encodeQueryParameters(Map<String, String> params) {
return params.entries
.map((MapEntry<String, String> e) =>
'${Uri.encodeComponent(e.key)}=${Uri.encodeComponent(e.value)}')
.join('&');
}
// #enddocregion encode-query-parameters

void main() => runApp(
MaterialApp(
home: Material(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: const <Widget>[
ElevatedButton(
onPressed: _composeMail,
child: Text('Compose an email'),
),
ElevatedButton(
onPressed: _composeSms,
child: Text('Compose a SMS'),
),
],
),
),
),
);

void _composeMail() {
// #docregion encode-query-parameters
final Uri emailLaunchUri = Uri(
scheme: 'mailto',
path: '[email protected]',
query: encodeQueryParameters(<String, String>{
'subject': 'Example Subject & Symbols are allowed!',
}),
);

launchUrl(emailLaunchUri);
// #enddocregion encode-query-parameters
}

void _composeSms() {
// #docregion sms
final Uri smsLaunchUri = Uri(
scheme: 'sms',
path: '0118 999 881 999 119 7253',
queryParameters: <String, String>{
'body': Uri.encodeComponent('Example Subject & Symbols are allowed!'),
},
);
// #enddocregion sms

launchUrl(smsLaunchUri);
}
47 changes: 47 additions & 0 deletions packages/url_launcher/url_launcher/example/lib/files.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Run this example with: flutter run -t lib/files.dart -d linux

// This file is used to extract code samples for the README.md file.
// Run update-excerpts if you modify this file.
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:path/path.dart' as p;
import 'package:url_launcher/url_launcher.dart';

void main() => runApp(
const MaterialApp(
home: Material(
child: Center(
child: ElevatedButton(
onPressed: _openFile,
child: Text('Open File'),
),
),
),
),
);

Future<void> _openFile() async {
// Prepare a file within tmp
final String tempFilePath = p.joinAll(<String>[
...p.split(Directory.systemTemp.path),
'flutter_url_launcher_example.txt'
]);
final File testFile = File(tempFilePath);
await testFile.writeAsString('Hello, world!');
// #docregion file
final String filePath = testFile.absolute.path;
final Uri uri = Uri.file(filePath);

if (!File(uri.toFilePath()).existsSync() || !await canLaunchUrl(uri)) {
throw "$uri does not exist, or there's no handler registered for it!";
}
if (!await launchUrl(uri)) {
throw 'Could not launch $uri';
}
// #enddocregion file
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ list(APPEND FLUTTER_PLUGIN_LIST
url_launcher_linux
)

list(APPEND FLUTTER_FFI_PLUGIN_LIST
)

set(PLUGIN_BUNDLED_LIBRARIES)

foreach(plugin ${FLUTTER_PLUGIN_LIST})
Expand All @@ -14,3 +17,8 @@ foreach(plugin ${FLUTTER_PLUGIN_LIST})
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
endforeach(plugin)

foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
endforeach(ffi_plugin)
2 changes: 2 additions & 0 deletions packages/url_launcher/url_launcher/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ environment:
dependencies:
flutter:
sdk: flutter
path: ^1.8.2
Copy link
Contributor

Choose a reason for hiding this comment

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

I think stable is on 1.8.0 or 1.8.1, which is probably why pub get is failing (which on CI is a timeout) in stable analysis.

Copy link
Member

Choose a reason for hiding this comment

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

Indeed:

Because every version of integration_test from sdk depends on path 1.8.1 and url_launcher_example depends on path ^1.8.2, integration_test from sdk is forbidden.
So, because url_launcher_example depends on integration_test from sdk, version solving failed.
Running "flutter pub get" in example...                                 
pub get failed (1; So, because url_launcher_example depends on integration_test from sdk, version solving failed.)

url_launcher:
# When depending on this package from a real application you should use:
# url_launcher: ^x.y.z
Expand All @@ -18,6 +19,7 @@ dependencies:
path: ../

dev_dependencies:
build_runner: ^2.1.10
flutter_driver:
sdk: flutter
integration_test:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ list(APPEND FLUTTER_PLUGIN_LIST
url_launcher_windows
)

list(APPEND FLUTTER_FFI_PLUGIN_LIST
)

set(PLUGIN_BUNDLED_LIBRARIES)

foreach(plugin ${FLUTTER_PLUGIN_LIST})
Expand All @@ -14,3 +17,8 @@ foreach(plugin ${FLUTTER_PLUGIN_LIST})
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
endforeach(plugin)

foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
endforeach(ffi_plugin)
Loading