Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all 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/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 5.1.0

* Add `headers` field to enable headers in the Android implementation.

## 5.0.5

* Add `enableDomStorage` field to `launch` to enable DOM storage in Android WebView.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Browser;
import android.view.KeyEvent;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
Expand All @@ -21,6 +23,8 @@
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry.Registrar;
import java.util.HashMap;
import java.util.Map;

/** UrlLauncherPlugin */
public class UrlLauncherPlugin implements MethodCallHandler {
Expand Down Expand Up @@ -66,10 +70,12 @@ private void canLaunch(String url, Result result) {

private void launch(MethodCall call, Result result, String url) {
Intent launchIntent;
boolean useWebView = call.argument("useWebView");
boolean enableJavaScript = call.argument("enableJavaScript");
boolean enableDomStorage = call.argument("enableDomStorage");
Activity activity = mRegistrar.activity();
final boolean useWebView = call.argument("useWebView");
final boolean enableJavaScript = call.argument("enableJavaScript");
final boolean enableDomStorage = call.argument("enableDomStorage");
final Map<String, String> headersMap = call.argument("headers");
final Activity activity = mRegistrar.activity();

if (activity == null) {
result.error("NO_ACTIVITY", "Launching a URL requires a foreground activity.", null);
return;
Expand All @@ -83,6 +89,10 @@ private void launch(MethodCall call, Result result, String url) {
launchIntent = new Intent(Intent.ACTION_VIEW);
launchIntent.setData(Uri.parse(url));
}

final Bundle headersBundle = extractBundle(headersMap);
launchIntent.putExtra(Browser.EXTRA_HEADERS, headersBundle);

activity.startActivity(launchIntent);
result.success(true);
}
Expand All @@ -93,6 +103,15 @@ private void closeWebView(Result result) {
result.success(null);
}

private Bundle extractBundle(Map<String, String> headersMap) {
final Bundle headersBundle = new Bundle();
for (String key : headersMap.keySet()) {
final String value = headersMap.get(key);
headersBundle.putString(key, value);
}
return headersBundle;
}

/* Launches WebView activity */
public static class WebViewActivity extends Activity {
private WebView webview;
Expand All @@ -104,23 +123,37 @@ public void onCreate(Bundle savedInstanceState) {
webview = new WebView(this);
setContentView(webview);
// Get the Intent that started this activity and extract the string
Intent intent = getIntent();
String url = intent.getStringExtra("url");
Boolean enableJavaScript = intent.getBooleanExtra("enableJavaScript", false);
Boolean enableDomStorage = intent.getBooleanExtra("enableDomStorage", false);
webview.loadUrl(url);
if (enableJavaScript) {
webview.getSettings().setJavaScriptEnabled(enableJavaScript);
}
if (enableDomStorage) {
webview.getSettings().setDomStorageEnabled(enableDomStorage);
}
final Intent intent = getIntent();
final String url = intent.getStringExtra("url");
final boolean enableJavaScript = intent.getBooleanExtra("enableJavaScript", false);
final boolean enableDomStorage = intent.getBooleanExtra("enableDomStorage", false);
final Bundle headersBundle = intent.getBundleExtra(Browser.EXTRA_HEADERS);

final Map<String, String> headersMap = extractHeaders(headersBundle);
webview.loadUrl(url, headersMap);

webview.getSettings().setJavaScriptEnabled(enableJavaScript);
webview.getSettings().setDomStorageEnabled(enableDomStorage);

// Open new urls inside the webview itself.
webview.setWebViewClient(
new WebViewClient() {

@Override
@SuppressWarnings("deprecation")
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure I understand why are we overriding this to call loadUrl on versions older than Lolipop?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You can verify why running the code in different emulators APIs, but the gist of it is that the first method is deprecated and should be used only in older versions of android, at the same time second method only exist in new API versions and they will not call the first one.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for following up!

I'm still not sure I understand - what breaks if we don't override shouldOverrideUrlLoading at all?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't quite remember, but I guess that is so the user can navigate using hyperlinks.
I didn't included the call to setWebViewClient, I just fixed the deprecation warning I was getting in Android Studio.

view.loadUrl(url);
return false;
}
return super.shouldOverrideUrlLoading(view, url);
}

@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
view.loadUrl(request.getUrl().toString());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
view.loadUrl(request.getUrl().toString());
}
return false;
}
});
Expand All @@ -139,6 +172,15 @@ public void onReceive(Context arg0, Intent intent) {
registerReceiver(broadcastReceiver, new IntentFilter("close"));
}

private Map<String, String> extractHeaders(Bundle headersBundle) {
final Map<String, String> headersMap = new HashMap<>();
for (String key : headersBundle.keySet()) {
final String value = headersBundle.getString(key);
headersMap.put(key, value);
}
return headersMap;
}

@Override
protected void onDestroy() {
super.onDestroy();
Expand Down
16 changes: 13 additions & 3 deletions packages/url_launcher/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,25 @@ class _MyHomePageState extends State<MyHomePage> {

Future<void> _launchInBrowser(String url) async {
if (await canLaunch(url)) {
await launch(url, forceSafariVC: false, forceWebView: false);
await launch(
url,
forceSafariVC: false,
forceWebView: false,
headers: <String, String>{'my_header_key': 'my_header_value'},
);
} else {
throw 'Could not launch $url';
}
}

Future<void> _launchInWebViewOrVC(String url) async {
if (await canLaunch(url)) {
await launch(url, forceSafariVC: true, forceWebView: true);
await launch(
url,
forceSafariVC: true,
forceWebView: true,
headers: <String, String>{'my_header_key': 'my_header_value'},
);
} else {
throw 'Could not launch $url';
}
Expand Down Expand Up @@ -112,7 +122,7 @@ class _MyHomePageState extends State<MyHomePage> {

@override
Widget build(BuildContext context) {
const String toLaunch = 'https://flutter.io';
const String toLaunch = 'https://www.cylog.org/headers/';
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
Expand Down
3 changes: 3 additions & 0 deletions packages/url_launcher/lib/url_launcher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const MethodChannel _channel = MethodChannel('plugins.flutter.io/url_launcher');
/// javascript.
/// [enableDomStorage] is an Android only setting. If true, WebView enable
/// DOM storage.
/// [headers] is an Android only setting that adds headers to the WebView.
///
/// Note that if any of the above are set to true but the URL is not a web URL,
/// this will throw a [PlatformException].
Expand All @@ -61,6 +62,7 @@ Future<bool> launch(
bool enableJavaScript,
bool enableDomStorage,
bool universalLinksOnly,
Map<String, String> headers,
Brightness statusBarBrightness,
}) async {
assert(urlString != null);
Expand Down Expand Up @@ -91,6 +93,7 @@ Future<bool> launch(
'enableJavaScript': enableJavaScript ?? false,
'enableDomStorage': enableDomStorage ?? false,
'universalLinksOnly': universalLinksOnly ?? false,
'headers': headers ?? <String, String>{},
},
);
if (statusBarBrightness != null) {
Expand Down
2 changes: 1 addition & 1 deletion packages/url_launcher/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ description: Flutter plugin for launching a URL on Android and iOS. Supports
web, phone, SMS, and email schemes.
author: Flutter Team <flutter-dev@googlegroups.com>
homepage: https://github.com/flutter/plugins/tree/master/packages/url_launcher
version: 5.0.5
version: 5.1.0

flutter:
plugin:
Expand Down
28 changes: 28 additions & 0 deletions packages/url_launcher/test/url_launcher_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,28 @@ void main() {
'enableJavaScript': false,
'enableDomStorage': false,
'universalLinksOnly': false,
'headers': <String, String>{},
})
],
);
});

test('launch with headers', () async {
await launch(
'http://example.com/',
headers: <String, String>{'key': 'value'},
);
expect(
log,
<Matcher>[
isMethodCall('launch', arguments: <String, Object>{
'url': 'http://example.com/',
'useSafariVC': true,
'useWebView': false,
'enableJavaScript': false,
'enableDomStorage': false,
'universalLinksOnly': false,
'headers': <String, String>{'key': 'value'},
})
],
);
Expand All @@ -59,6 +81,7 @@ void main() {
'enableJavaScript': false,
'enableDomStorage': false,
'universalLinksOnly': false,
'headers': <String, String>{},
})
],
);
Expand All @@ -77,6 +100,7 @@ void main() {
'enableJavaScript': false,
'enableDomStorage': false,
'universalLinksOnly': true,
'headers': <String, String>{},
})
],
);
Expand All @@ -94,6 +118,7 @@ void main() {
'enableJavaScript': false,
'enableDomStorage': false,
'universalLinksOnly': false,
'headers': <String, String>{},
})
],
);
Expand All @@ -112,6 +137,7 @@ void main() {
'enableJavaScript': true,
'enableDomStorage': false,
'universalLinksOnly': false,
'headers': <String, String>{},
})
],
);
Expand All @@ -130,6 +156,7 @@ void main() {
'enableJavaScript': false,
'enableDomStorage': true,
'universalLinksOnly': false,
'headers': <String, String>{},
})
],
);
Expand All @@ -147,6 +174,7 @@ void main() {
'enableJavaScript': false,
'enableDomStorage': false,
'universalLinksOnly': false,
'headers': <String, String>{},
})
],
);
Expand Down