Commit 5c402c09 authored by 李增强's avatar 李增强

Initial commit

parents
## 5.7.10
* Update Dart SDK constraint in example.
## 5.7.9
* Check in windows/ directory for example/
## 5.7.8
* Fixed a situation where an app would crash if the url_launcher’s `launch` method can’t find an app to open the provided url. It will now throw a clear Dart PlatformException.
## 5.7.7
* Introduce the Link widget with an implementation for native platforms.
## 5.7.6
* Suppress deprecation warning on the `shouldOverrideUrlLoading` method on Android of the `FlutterWebChromeClient` class.
## 5.7.5
* Improved documentation of the `headers` parameter.
## 5.7.4
* Update android compileSdkVersion to 29.
## 5.7.3
* Check in linux/ directory for example/
## 5.7.2
* Add API documentation explaining the [canLaunch] method returns `false` if package visibility (Android API 30) is not managed correctly.
## 5.7.1
* Keep handling deprecated Android v1 classes for backward compatibility.
## 5.7.0
* Handle WebView multi-window support.
## 5.6.0
* Support Windows by default.
## 5.5.3
* Suppress deprecation warning on the `shouldOverrideUrlLoading` method on Android.
## 5.5.2
* Depend explicitly on the `platform_interface` package that adds the `webOnlyWindowName` parameter.
## 5.5.1
* Added webOnlyWindowName parameter to launch()
## 5.5.0
* Support Linux by default.
## 5.4.11
* Add documentation in README suggesting how to properly encode urls with special characters.
## 5.4.10
* Post-v2 Android embedding cleanups.
## 5.4.9
* Update README.
## 5.4.8
* Initialize `previousAutomaticSystemUiAdjustment` in launch method.
## 5.4.7
* Update lower bound of dart dependency to 2.1.0.
## 5.4.6
* Add `web` to the example app.
## 5.4.5
* Remove Android dependencies fallback.
* Require Flutter SDK 1.12.13+hotfix.5 or greater.
* Fix CocoaPods podspec lint warnings.
## 5.4.4
* Replace deprecated `getFlutterEngine` call on Android.
## 5.4.3
* Fixed the launchUniversalLinkIos method.
## 5.4.2
* Make the pedantic dev_dependency explicit.
## 5.4.1
* Update unit tests to work with the PlatformInterface from package `plugin_platform_interface`.
## 5.4.0
* Support macOS by default.
## 5.3.0
* Support web by default.
* Use the new plugins pubspec schema.
## 5.2.7
* Minor unit test changes and added a lint for public DartDocs.
## 5.2.6
* Remove AndroidX warnings.
## 5.2.5
* Include lifecycle dependency as a compileOnly one on Android to resolve
potential version conflicts with other transitive libraries.
## 5.2.4
* Use `package:url_launcher_platform_interface` to get the platform-specific implementation.
## 5.2.3
* Android: Use android.arch.lifecycle instead of androidx.lifecycle:lifecycle in `build.gradle` to support apps that has not been migrated to AndroidX.
## 5.2.2
* Re-land embedder v2 support with correct Flutter SDK constraints.
## 5.2.1
* Revert the migration since the Flutter dependency was too low.
## 5.2.0
* Migrate the plugin to use the V2 Android engine embedding. This shouldn't
affect existing functionality. Plugin authors who use the V2 embedding can now
instantiate the plugin and expect that it correctly responds to app lifecycle
changes.
## 5.1.7
* Define clang module for iOS.
## 5.1.6
* Fixes bug where androidx app won't build with this plugin by enabling androidx and jetifier in the android `gradle.properties`.
## 5.1.5
* Update homepage url after moving to federated directory.
## 5.1.4
* Update and migrate iOS example project.
## 5.1.3
* Always launch url from the top most UIViewController in iOS.
## 5.1.2
* Update AGP and gradle.
* Split plugin and WebViewActivity class files.
## 5.1.1
* Suppress a handled deprecation warning on iOS
## 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.
## 5.0.4
* Update Dart code to conform to current Dart formatter.
## 5.0.3
* Add missing template type parameter to `invokeMethod` calls.
* Bump minimum Flutter version to 1.5.0.
* Replace invokeMethod with invokeMapMethod wherever necessary.
## 5.0.2
* Fixes `closeWebView` failure on iOS.
## 5.0.1
* Log a more detailed warning at build time about the previous AndroidX
migration.
## 5.0.0
* **Breaking change**. Migrate from the deprecated original Android Support
Library to AndroidX. This shouldn't result in any functional changes, but it
requires any Android apps using this plugin to [also
migrate](https://developer.android.com/jetpack/androidx/migrate) if they're
using the original support library.
This was originally incorrectly pushed in the `4.2.0` update.
## 4.2.0+3
* **Revert the breaking 4.2.0 update**. 4.2.0 was known to be breaking and
should have incremented the major version number instead of the minor. This
revert is in and of itself breaking for anyone that has already migrated
however. Anyone who has already migrated their app to AndroidX should
immediately update to `5.0.0` instead. That's the correctly versioned new push
of `4.2.0`.
## 4.2.0+2
* Updated `launch` to use async and await, fixed the incorrect return value by `launch` method.
## 4.2.0+1
* Refactored the Java and Objective-C code. Replaced instance variables with properties in Objective-C.
## 4.2.0
* **BAD**. This was a breaking change that was incorrectly published on a minor
version upgrade, should never have happened. Reverted by 4.2.0+3.
* **Breaking change**. Migrate from the deprecated original Android Support
Library to AndroidX. This shouldn't result in any functional changes, but it
requires any Android apps using this plugin to [also
migrate](https://developer.android.com/jetpack/androidx/migrate) if they're
using the original support library.
## 4.1.0+1
* This is just a version bump to republish as 4.1.0 was published with some dirty local state.
## 4.1.0
* Added `universalLinksOnly` setting.
* Updated `launch` to return `Future<bool>`.
## 4.0.3
* Fixed launch url fail for Android: `launch` now assert activity not null and using activity to startActivity.
* Fixed `WebViewActivity has leaked IntentReceiver` for Android.
## 4.0.2
* Added `closeWebView` function to programmatically close the current WebView.
## 4.0.1
* Added enableJavaScript field to `launch` to enable javascript in Android WebView.
## 4.0.0
* **Breaking change** Now requires a minimum Flutter version of 0.5.6.
* Update to statusBarBrightness field so that the logic runs on the Flutter side.
* **Breaking change** statusBarBrightness no longer has a default value.
## 3.0.3
* Added statusBarBrightness field to `launch` to set iOS status bar brightness.
## 3.0.2
* Updated Gradle tooling to match Android Studio 3.1.2.
## 3.0.1
* Fix a crash during Safari view controller dismiss.
## 3.0.0
* **Breaking change**. Set SDK constraints to match the Flutter beta release.
## 2.0.2
* Fixed Dart 2 issue: `launch` now returns `Future<void>` instead of
`Future<Null>`.
## 2.0.1
* Simplified and upgraded Android project template to Android SDK 27.
* Updated package description.
## 2.0.0
* **Breaking change**. Upgraded to Gradle 4.1 and Android Studio Gradle plugin
3.0.1. Older Flutter projects need to upgrade their Gradle setup as well in
order to use this version of the plugin. Instructions can be found
[here](https://github.com/flutter/flutter/wiki/Updating-Flutter-projects-to-Gradle-4.1-and-Android-Studio-Gradle-plugin-3.0.1).
## 1.0.3
* Add FLT prefix to iOS types.
## 1.0.2
* Fix handling of URLs in Android WebView.
## 1.0.1
* Support option to launch default browser in iOS.
* Parse incoming url and decide on what to open based on scheme.
* Support WebView on Android.
## 1.0.0
* iOS plugin presents a Safari view controller instead of switching to the Safari app.
## 0.4.2+5
* Aligned author name with rest of repo.
## 0.4.2+2, 0.4.2+3, 0.4.2+4
* Updated README.
## 0.4.2+1
* Updated README.
## 0.4.2
* Change to README.md.
## 0.4.1
* Upgrade Android SDK Build Tools to 25.0.3.
## 0.4.0
* Upgrade to new plugin registration.
## 0.3.6
* Fix workaround for failing dynamic check in Xcode 7/sdk version 9.
## 0.3.5
* Workaround for failing dynamic check in Xcode 7/sdk version 9.
## 0.3.4
* Add test.
## 0.3.3
* Change to buildToolsVersion.
## 0.3.2
* Change to README.md.
## 0.3.1
* Change to README.md.
## 0.3.0
* Add `canLaunch` method.
## 0.2.0
* Change `launch` to a top-level method instead of a static method in a class.
## 0.1.1
* Change to README.md.
## 0.1.0
* Initial Open Source release.
Copyright 2017 The Chromium Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# url_launcher
[![pub package](https://img.shields.io/pub/v/url_launcher.svg)](https://pub.dartlang.org/packages/url_launcher)
A Flutter plugin for launching a URL in the mobile platform. Supports
iOS, Android, web, Windows, macOS, and Linux.
## Usage
To use this plugin, add `url_launcher` as a [dependency in your pubspec.yaml file](https://flutter.dev/platform-plugins/).
### Example
``` dart
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
void main() {
runApp(Scaffold(
body: Center(
child: RaisedButton(
onPressed: _launchURL,
child: Text('Show Flutter homepage'),
),
),
));
}
_launchURL() async {
const url = 'https://flutter.dev';
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}
```
## Supported URL schemes
The [`launch`](https://www.dartdocs.org/documentation/url_launcher/latest/url_launcher/launch.html) method
takes a string argument containing a URL. This URL
can be formatted using a number of different URL schemes. The supported
URL schemes depend on the underlying platform and installed apps.
Common schemes supported by both iOS and Android:
| Scheme | Action |
|---|---|
| `http:<URL>` , `https:<URL>`, e.g. `http://flutter.dev` | Open URL in the default browser |
| `mailto:<email address>?subject=<subject>&body=<body>`, e.g. `mailto:smith@example.org?subject=News&body=New%20plugin` | Create email to <email address> in the default email app |
| `tel:<phone number>`, e.g. `tel:+1 555 010 999` | Make a phone call to <phone number> using the default phone app |
| `sms:<phone number>`, e.g. `sms:5550101234` | Send an SMS message to <phone number> using the default messaging app |
More details can be found here for [iOS](https://developer.apple.com/library/content/featuredarticles/iPhoneURLScheme_Reference/Introduction/Introduction.html) and [Android](https://developer.android.com/guide/components/intents-common.html)
### Encoding URLs
URLs must be properly encoded, especially when including spaces or other special characters. This can be done using the [`Uri` class](https://api.dart.dev/stable/2.7.1/dart-core/Uri-class.html):
```dart
import 'dart:core';
import 'package:url_launcher/url_launcher.dart';
final Uri _emailLaunchUri = Uri(
scheme: 'mailto',
path: 'smith@example.com',
queryParameters: {
'subject': 'Example Subject & Symbols are allowed!'
}
);
// ...
// mailto:smith@example.com?subject=Example+Subject+%26+Symbols+are+allowed%21
launch(_emailLaunchUri.toString());
```
## Handling missing URL receivers
A particular mobile device may not be able to receive all supported URL schemes.
For example, a tablet may not have a cellular radio and thus no support for
launching a URL using the `sms` scheme, or a device may not have an email app
and thus no support for launching a URL using the `email` scheme.
We recommend checking which URL schemes are supported using the
[`canLaunch`](https://www.dartdocs.org/documentation/url_launcher/latest/url_launcher/canLaunch.html)
method prior to calling `launch`. If the `canLaunch` method returns false, as a
best practice we suggest adjusting the application UI so that the unsupported
URL is never triggered; for example, if the `email` scheme is not supported, a
UI button that would have sent email can be changed to redirect the user to a
web page using a URL following the `http` scheme.
## Browser vs In-app Handling
By default, Android opens up a browser when handling URLs. You can pass
`forceWebView: true` parameter to tell the plugin to open a WebView instead.
If you do this for a URL of a page containing JavaScript, make sure to pass in
`enableJavaScript: true`, or else the launch method will not work properly. On
iOS, the default behavior is to open all web URLs within the app. Everything
else is redirected to the app handler.
group 'io.flutter.plugins.urllauncher'
version '1.0-SNAPSHOT'
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.2'
}
}
rootProject.allprojects {
repositories {
google()
jcenter()
}
}
apply plugin: 'com.android.library'
android {
compileSdkVersion 29
defaultConfig {
minSdkVersion 16
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
lintOptions {
disable 'InvalidPackage'
}
testOptions {
unitTests.includeAndroidResources = true
}
}
dependencies {
compileOnly 'androidx.annotation:annotation:1.0.0'
testImplementation 'junit:junit:4.12'
testImplementation 'org.mockito:mockito-core:1.10.19'
testImplementation 'androidx.test:core:1.0.0'
testImplementation 'org.robolectric:robolectric:4.3'
}
org.gradle.jvmargs=-Xmx1536M
rootProject.name = 'url_launcher'
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.flutter.plugins.urllauncher">
<application>
<activity android:name="io.flutter.plugins.urllauncher.WebViewActivity"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:exported="false"/>
</application>
</manifest>
package io.flutter.plugins.urllauncher;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.Nullable;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugins.urllauncher.UrlLauncher.LaunchStatus;
import java.util.Map;
/**
* Translates incoming UrlLauncher MethodCalls into well formed Java function calls for {@link
* UrlLauncher}.
*/
final class MethodCallHandlerImpl implements MethodCallHandler {
private static final String TAG = "MethodCallHandlerImpl";
private final UrlLauncher urlLauncher;
@Nullable private MethodChannel channel;
/** Forwards all incoming MethodChannel calls to the given {@code urlLauncher}. */
MethodCallHandlerImpl(UrlLauncher urlLauncher) {
this.urlLauncher = urlLauncher;
}
@Override
public void onMethodCall(MethodCall call, Result result) {
final String url = call.argument("url");
switch (call.method) {
case "canLaunch":
onCanLaunch(result, url);
break;
case "launch":
onLaunch(call, result, url);
break;
case "closeWebView":
onCloseWebView(result);
break;
default:
result.notImplemented();
break;
}
}
/**
* Registers this instance as a method call handler on the given {@code messenger}.
*
* <p>Stops any previously started and unstopped calls.
*
* <p>This should be cleaned with {@link #stopListening} once the messenger is disposed of.
*/
void startListening(BinaryMessenger messenger) {
if (channel != null) {
Log.wtf(TAG, "Setting a method call handler before the last was disposed.");
stopListening();
}
channel = new MethodChannel(messenger, "plugins.flutter.io/url_launcher");
channel.setMethodCallHandler(this);
}
/**
* Clears this instance from listening to method calls.
*
* <p>Does nothing if {@link #startListening} hasn't been called, or if we're already stopped.
*/
void stopListening() {
if (channel == null) {
Log.d(TAG, "Tried to stop listening when no MethodChannel had been initialized.");
return;
}
channel.setMethodCallHandler(null);
channel = null;
}
private void onCanLaunch(Result result, String url) {
result.success(urlLauncher.canLaunch(url));
}
private void onLaunch(MethodCall call, Result result, String url) {
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 Bundle headersBundle = extractBundle(headersMap);
LaunchStatus launchStatus =
urlLauncher.launch(url, headersBundle, useWebView, enableJavaScript, enableDomStorage);
if (launchStatus == LaunchStatus.NO_ACTIVITY) {
result.error("NO_ACTIVITY", "Launching a URL requires a foreground activity.", null);
} else if (launchStatus == LaunchStatus.ACTIVITY_NOT_FOUND) {
result.error(
"ACTIVITY_NOT_FOUND",
String.format("No Activity found to handle intent { %s }", url),
null);
} else {
result.success(true);
}
}
private void onCloseWebView(Result result) {
urlLauncher.closeWebView();
result.success(null);
}
private static 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;
}
}
package io.flutter.plugins.urllauncher;
import android.app.Activity;
import android.app.Application;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Browser;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
/**
* Launches components for URLs.
*/
class UrlLauncher {
private final Context applicationContext;
@Nullable
private Activity mCurrentActiveActivity;
/**
* Uses the given {@code applicationContext} for launching intents.
*
* <p>It may be null initially, but should be set before calling {@link #launch}.
*/
UrlLauncher(Context applicationContext, @Nullable Activity activity) {
this.applicationContext = applicationContext;
this.mCurrentActiveActivity = activity;
if (activity != null) {
abActivity(activity);
}
}
void setmCurrentActiveActivity(@Nullable Activity activity) {
if (this.mCurrentActiveActivity != null) {
return;
}
this.mCurrentActiveActivity = activity;
abActivity(activity);
}
void abActivity(Activity activity) {
activity.getApplication().registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
mCurrentActiveActivity = activity;
}
@Override
public void onActivityStarted(Activity activity) {
mCurrentActiveActivity = activity;
}
@Override
public void onActivityResumed(Activity activity) {
mCurrentActiveActivity = activity;
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
if (mCurrentActiveActivity == activity) {
mCurrentActiveActivity = null;
}
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
if (mCurrentActiveActivity == activity) {
mCurrentActiveActivity = null;
}
}
});
}
/**
* Returns whether the given {@code url} resolves into an existing component.
*/
boolean canLaunch(String url) {
Intent launchIntent = new Intent(Intent.ACTION_VIEW);
launchIntent.setData(Uri.parse(url));
ComponentName componentName =
launchIntent.resolveActivity(applicationContext.getPackageManager());
return componentName != null
&& !"{com.android.fallback/com.android.fallback.Fallback}"
.equals(componentName.toShortString());
}
/**
* Attempts to launch the given {@code url}.
*
* @param headersBundle forwarded to the intent as {@code Browser.EXTRA_HEADERS}.
* @param useWebView when true, the URL is launched inside of {@link WebViewActivity}.
* @param enableJavaScript Only used if {@param useWebView} is true. Enables JS in the WebView.
* @param enableDomStorage Only used if {@param useWebView} is true. Enables DOM storage in the
* @return {@link LaunchStatus#NO_ACTIVITY} if there's no available {@code applicationContext}.
* {@link LaunchStatus#ACTIVITY_NOT_FOUND} if there's no activity found to handle {@code
* launchIntent}. {@link LaunchStatus#OK} otherwise.
*/
LaunchStatus launch(
String url,
Bundle headersBundle,
boolean useWebView,
boolean enableJavaScript,
boolean enableDomStorage) {
if (mCurrentActiveActivity == null) {
return LaunchStatus.NO_ACTIVITY;
}
Intent launchIntent;
if (useWebView) {
launchIntent =
WebViewActivity.createIntent(
mCurrentActiveActivity, url, enableJavaScript, enableDomStorage, headersBundle);
} else {
launchIntent =
new Intent(Intent.ACTION_VIEW)
.setData(Uri.parse(url))
.putExtra(Browser.EXTRA_HEADERS, headersBundle);
}
try {
mCurrentActiveActivity.startActivity(launchIntent);
} catch (ActivityNotFoundException e) {
return LaunchStatus.ACTIVITY_NOT_FOUND;
}
return LaunchStatus.OK;
}
/**
* Closes any activities started with {@link #launch} {@code useWebView=true}.
*/
void closeWebView() {
applicationContext.sendBroadcast(new Intent(WebViewActivity.ACTION_CLOSE));
}
/**
* Result of a {@link #launch} call.
*/
enum LaunchStatus {
/**
* The intent was well formed.
*/
OK,
/**
* No activity was found to launch.
*/
NO_ACTIVITY,
/**
* No Activity found that can handle given intent.
*/
ACTIVITY_NOT_FOUND,
}
}
package io.flutter.plugins.urllauncher;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
/**
* Plugin implementation that uses the new {@code io.flutter.embedding} package.
*
* <p>Instantiate this in an add to app scenario to gracefully handle activity and context changes.
*/
public final class UrlLauncherPlugin implements FlutterPlugin, ActivityAware {
private static final String TAG = "UrlLauncherPlugin";
@Nullable private MethodCallHandlerImpl methodCallHandler;
@Nullable private UrlLauncher urlLauncher;
/**
* Registers a plugin implementation that uses the stable {@code io.flutter.plugin.common}
* package.
*
* <p>Calling this automatically initializes the plugin. However plugins initialized this way
* won't react to changes in activity or context, unlike {@link UrlLauncherPlugin}.
*/
@SuppressWarnings("deprecation")
public static void registerWith(io.flutter.plugin.common.PluginRegistry.Registrar registrar) {
MethodCallHandlerImpl handler =
new MethodCallHandlerImpl(new UrlLauncher(registrar.context(), registrar.activity()));
handler.startListening(registrar.messenger());
}
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
urlLauncher = new UrlLauncher(binding.getApplicationContext(), /*activity=*/ null);
methodCallHandler = new MethodCallHandlerImpl(urlLauncher);
methodCallHandler.startListening(binding.getBinaryMessenger());
}
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
if (methodCallHandler == null) {
Log.wtf(TAG, "Already detached from the engine.");
return;
}
methodCallHandler.stopListening();
methodCallHandler = null;
urlLauncher = null;
}
@Override
public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
if (methodCallHandler == null) {
Log.wtf(TAG, "urlLauncher was never set.");
return;
}
urlLauncher.setmCurrentActiveActivity(binding.getActivity());
}
@Override
public void onDetachedFromActivity() {
if (methodCallHandler == null) {
Log.wtf(TAG, "urlLauncher was never set.");
return;
}
urlLauncher.setmCurrentActiveActivity(null);
}
@Override
public void onDetachedFromActivityForConfigChanges() {
onDetachedFromActivity();
}
@Override
public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
onAttachedToActivity(binding);
}
}
package io.flutter.plugins.urllauncher;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import android.os.Message;
import android.provider.Browser;
import android.view.KeyEvent;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import java.util.HashMap;
import java.util.Map;
/* Launches WebView activity */
public class WebViewActivity extends Activity {
/*
* Use this to trigger a BroadcastReceiver inside WebViewActivity
* that will request the current instance to finish.
* */
public static String ACTION_CLOSE = "close action";
private final BroadcastReceiver broadcastReceiver =
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_CLOSE.equals(action)) {
finish();
}
}
};
private final WebViewClient webViewClient =
new WebViewClient() {
/*
* This method is deprecated in API 24. Still overridden to support
* earlier Android versions.
*/
@SuppressWarnings("deprecation")
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
view.loadUrl(url);
return false;
}
return super.shouldOverrideUrlLoading(view, url);
}
@RequiresApi(Build.VERSION_CODES.N)
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
view.loadUrl(request.getUrl().toString());
}
return false;
}
};
private WebView webview;
private IntentFilter closeIntentFilter = new IntentFilter(ACTION_CLOSE);
// Verifies that a url opened by `Window.open` has a secure url.
private class FlutterWebChromeClient extends WebChromeClient {
@Override
public boolean onCreateWindow(
final WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
final WebViewClient webViewClient =
new WebViewClient() {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public boolean shouldOverrideUrlLoading(
@NonNull WebView view, @NonNull WebResourceRequest request) {
webview.loadUrl(request.getUrl().toString());
return true;
}
/*
* This method is deprecated in API 24. Still overridden to support
* earlier Android versions.
*/
@SuppressWarnings("deprecation")
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
webview.loadUrl(url);
return true;
}
};
final WebView newWebView = new WebView(webview.getContext());
newWebView.setWebViewClient(webViewClient);
final WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
transport.setWebView(newWebView);
resultMsg.sendToTarget();
return true;
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
webview = new WebView(this);
setContentView(webview);
// Get the Intent that started this activity and extract the string
final Intent intent = getIntent();
final String url = intent.getStringExtra(URL_EXTRA);
final boolean enableJavaScript = intent.getBooleanExtra(ENABLE_JS_EXTRA, false);
final boolean enableDomStorage = intent.getBooleanExtra(ENABLE_DOM_EXTRA, 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(webViewClient);
// Multi windows is set with FlutterWebChromeClient by default to handle internal bug: b/159892679.
webview.getSettings().setSupportMultipleWindows(true);
webview.setWebChromeClient(new FlutterWebChromeClient());
// Register receiver that may finish this Activity.
registerReceiver(broadcastReceiver, closeIntentFilter);
}
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();
unregisterReceiver(broadcastReceiver);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && webview.canGoBack()) {
webview.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
private static String URL_EXTRA = "url";
private static String ENABLE_JS_EXTRA = "enableJavaScript";
private static String ENABLE_DOM_EXTRA = "enableDomStorage";
/* Hides the constants used to forward data to the Activity instance. */
public static Intent createIntent(
Context context,
String url,
boolean enableJavaScript,
boolean enableDomStorage,
Bundle headersBundle) {
return new Intent(context, WebViewActivity.class)
.putExtra(URL_EXTRA, url)
.putExtra(ENABLE_JS_EXTRA, enableJavaScript)
.putExtra(ENABLE_DOM_EXTRA, enableDomStorage)
.putExtra(Browser.EXTRA_HEADERS, headersBundle);
}
}
package io.flutter.plugins.urllauncher;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.os.Bundle;
import androidx.test.core.app.ApplicationProvider;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.BinaryMessenger.BinaryMessageHandler;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel.Result;
import java.util.HashMap;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
@RunWith(RobolectricTestRunner.class)
public class MethodCallHandlerImplTest {
private static final String CHANNEL_NAME = "plugins.flutter.io/url_launcher";
private UrlLauncher urlLauncher;
private MethodCallHandlerImpl methodCallHandler;
@Before
public void setUp() {
urlLauncher = new UrlLauncher(ApplicationProvider.getApplicationContext(), /*activity=*/ null);
methodCallHandler = new MethodCallHandlerImpl(urlLauncher);
}
@Test
public void startListening_registersChannel() {
BinaryMessenger messenger = mock(BinaryMessenger.class);
methodCallHandler.startListening(messenger);
verify(messenger, times(1))
.setMessageHandler(eq(CHANNEL_NAME), any(BinaryMessageHandler.class));
}
@Test
public void startListening_unregistersExistingChannel() {
BinaryMessenger firstMessenger = mock(BinaryMessenger.class);
BinaryMessenger secondMessenger = mock(BinaryMessenger.class);
methodCallHandler.startListening(firstMessenger);
methodCallHandler.startListening(secondMessenger);
// Unregisters the first and then registers the second.
verify(firstMessenger, times(1)).setMessageHandler(CHANNEL_NAME, null);
verify(secondMessenger, times(1))
.setMessageHandler(eq(CHANNEL_NAME), any(BinaryMessageHandler.class));
}
@Test
public void stopListening_unregistersExistingChannel() {
BinaryMessenger messenger = mock(BinaryMessenger.class);
methodCallHandler.startListening(messenger);
methodCallHandler.stopListening();
verify(messenger, times(1)).setMessageHandler(CHANNEL_NAME, null);
}
@Test
public void stopListening_doesNothingWhenUnset() {
BinaryMessenger messenger = mock(BinaryMessenger.class);
methodCallHandler.stopListening();
verify(messenger, never()).setMessageHandler(CHANNEL_NAME, null);
}
@Test
public void onMethodCall_canLaunchReturnsTrue() {
urlLauncher = mock(UrlLauncher.class);
methodCallHandler = new MethodCallHandlerImpl(urlLauncher);
String url = "foo";
when(urlLauncher.canLaunch(url)).thenReturn(true);
Result result = mock(Result.class);
Map<String, Object> args = new HashMap<>();
args.put("url", url);
methodCallHandler.onMethodCall(new MethodCall("canLaunch", args), result);
verify(result, times(1)).success(true);
}
@Test
public void onMethodCall_canLaunchReturnsFalse() {
urlLauncher = mock(UrlLauncher.class);
methodCallHandler = new MethodCallHandlerImpl(urlLauncher);
String url = "foo";
when(urlLauncher.canLaunch(url)).thenReturn(false);
Result result = mock(Result.class);
Map<String, Object> args = new HashMap<>();
args.put("url", url);
methodCallHandler.onMethodCall(new MethodCall("canLaunch", args), result);
verify(result, times(1)).success(false);
}
@Test
public void onMethodCall_launchReturnsNoActivityError() {
// Setup mock objects
urlLauncher = mock(UrlLauncher.class);
Result result = mock(Result.class);
// Setup expected values
String url = "foo";
boolean useWebView = false;
boolean enableJavaScript = false;
boolean enableDomStorage = false;
// Setup arguments map send on the method channel
Map<String, Object> args = new HashMap<>();
args.put("url", url);
args.put("useWebView", useWebView);
args.put("enableJavaScript", enableJavaScript);
args.put("enableDomStorage", enableDomStorage);
args.put("headers", new HashMap<>());
// Mock the launch method on the urlLauncher class
when(urlLauncher.launch(
eq(url), any(Bundle.class), eq(useWebView), eq(enableJavaScript), eq(enableDomStorage)))
.thenReturn(UrlLauncher.LaunchStatus.NO_ACTIVITY);
// Act by calling the "launch" method on the method channel
methodCallHandler = new MethodCallHandlerImpl(urlLauncher);
methodCallHandler.onMethodCall(new MethodCall("launch", args), result);
// Verify the results and assert
verify(result, times(1))
.error("NO_ACTIVITY", "Launching a URL requires a foreground activity.", null);
}
@Test
public void onMethodCall_launchReturnsActivityNotFoundError() {
// Setup mock objects
urlLauncher = mock(UrlLauncher.class);
Result result = mock(Result.class);
// Setup expected values
String url = "foo";
boolean useWebView = false;
boolean enableJavaScript = false;
boolean enableDomStorage = false;
// Setup arguments map send on the method channel
Map<String, Object> args = new HashMap<>();
args.put("url", url);
args.put("useWebView", useWebView);
args.put("enableJavaScript", enableJavaScript);
args.put("enableDomStorage", enableDomStorage);
args.put("headers", new HashMap<>());
// Mock the launch method on the urlLauncher class
when(urlLauncher.launch(
eq(url), any(Bundle.class), eq(useWebView), eq(enableJavaScript), eq(enableDomStorage)))
.thenReturn(UrlLauncher.LaunchStatus.ACTIVITY_NOT_FOUND);
// Act by calling the "launch" method on the method channel
methodCallHandler = new MethodCallHandlerImpl(urlLauncher);
methodCallHandler.onMethodCall(new MethodCall("launch", args), result);
// Verify the results and assert
verify(result, times(1))
.error(
"ACTIVITY_NOT_FOUND",
String.format("No Activity found to handle intent { %s }", url),
null);
}
@Test
public void onMethodCall_launchReturnsTrue() {
// Setup mock objects
urlLauncher = mock(UrlLauncher.class);
Result result = mock(Result.class);
// Setup expected values
String url = "foo";
boolean useWebView = false;
boolean enableJavaScript = false;
boolean enableDomStorage = false;
// Setup arguments map send on the method channel
Map<String, Object> args = new HashMap<>();
args.put("url", url);
args.put("useWebView", useWebView);
args.put("enableJavaScript", enableJavaScript);
args.put("enableDomStorage", enableDomStorage);
args.put("headers", new HashMap<>());
// Mock the launch method on the urlLauncher class
when(urlLauncher.launch(
eq(url), any(Bundle.class), eq(useWebView), eq(enableJavaScript), eq(enableDomStorage)))
.thenReturn(UrlLauncher.LaunchStatus.OK);
// Act by calling the "launch" method on the method channel
methodCallHandler = new MethodCallHandlerImpl(urlLauncher);
methodCallHandler.onMethodCall(new MethodCall("launch", args), result);
// Verify the results and assert
verify(result, times(1)).success(true);
}
@Test
public void onMethodCall_closeWebView() {
urlLauncher = mock(UrlLauncher.class);
methodCallHandler = new MethodCallHandlerImpl(urlLauncher);
String url = "foo";
when(urlLauncher.canLaunch(url)).thenReturn(true);
Result result = mock(Result.class);
Map<String, Object> args = new HashMap<>();
args.put("url", url);
methodCallHandler.onMethodCall(new MethodCall("closeWebView", args), result);
verify(urlLauncher, times(1)).closeWebView();
verify(result, times(1)).success(null);
}
}
This diff is collapsed.
# This is a generated file; do not edit or check into version control.
url_launcher_linux=C:\\Users\\qiaomeng\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\url_launcher_linux-0.0.1+4\\
url_launcher_macos=C:\\Users\\qiaomeng\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\url_launcher_macos-0.0.1+9\\
url_launcher_web=C:\\Users\\qiaomeng\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\url_launcher_web-0.1.5+3\\
url_launcher_windows=C:\\Users\\qiaomeng\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\url_launcher_windows-0.0.1+3\\
url_launcher=D:\\android_project\\url_launcher\\
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"url_launcher","path":"D:\\\\android_project\\\\url_launcher\\\\","dependencies":[]}],"android":[{"name":"url_launcher","path":"D:\\\\android_project\\\\url_launcher\\\\","dependencies":[]}],"macos":[{"name":"url_launcher_macos","path":"C:\\\\Users\\\\qiaomeng\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\url_launcher_macos-0.0.1+9\\\\","dependencies":[]}],"linux":[{"name":"url_launcher_linux","path":"C:\\\\Users\\\\qiaomeng\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\url_launcher_linux-0.0.1+4\\\\","dependencies":[]}],"windows":[{"name":"url_launcher_windows","path":"C:\\\\Users\\\\qiaomeng\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\url_launcher_windows-0.0.1+3\\\\","dependencies":[]}],"web":[{"name":"url_launcher_web","path":"C:\\\\Users\\\\qiaomeng\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\url_launcher_web-0.1.5+3\\\\","dependencies":[]}]},"dependencyGraph":[{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_web","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_web","url_launcher_linux","url_launcher_macos","url_launcher_windows"]}],"date_created":"2021-03-16 10:13:54.698722","version":"1.22.4"}
\ No newline at end of file
# Generated by pub on 2021-03-16 10:13:54.516432.
_fe_analyzer_shared:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/_fe_analyzer_shared-14.0.0/lib/
analyzer:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/analyzer-0.41.2/lib/
archive:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/archive-2.0.13/lib/
args:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/args-1.6.0/lib/
async:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/async-2.5.0-nullsafety.1/lib/
boolean_selector:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/boolean_selector-2.1.0-nullsafety.1/lib/
build:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/build-1.6.2/lib/
built_collection:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/built_collection-4.3.2/lib/
built_value:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/built_value-7.1.0/lib/
characters:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/characters-1.1.0-nullsafety.3/lib/
charcode:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/charcode-1.2.0-nullsafety.1/lib/
cli_util:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/cli_util-0.2.0/lib/
clock:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/clock-1.1.0-nullsafety.1/lib/
code_builder:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/code_builder-3.7.0/lib/
collection:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/collection-1.15.0-nullsafety.3/lib/
convert:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/convert-2.1.1/lib/
crypto:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/crypto-2.1.5/lib/
dart_style:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/dart_style-1.3.12/lib/
fake_async:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/fake_async-1.2.0-nullsafety.1/lib/
file:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/file-6.0.0-nullsafety.2/lib/
fixnum:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/fixnum-0.10.11/lib/
flutter:file:///D:/dev/flutter/packages/flutter/lib/
flutter_driver:file:///D:/dev/flutter/packages/flutter_driver/lib/
flutter_test:file:///D:/dev/flutter/packages/flutter_test/lib/
flutter_web_plugins:file:///D:/dev/flutter/packages/flutter_web_plugins/lib/
fuchsia_remote_debug_protocol:file:///D:/dev/flutter/packages/fuchsia_remote_debug_protocol/lib/
glob:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/glob-1.2.0/lib/
js:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/js-0.6.2/lib/
json_rpc_2:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/json_rpc_2-2.2.2/lib/
logging:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/logging-0.11.4/lib/
matcher:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/matcher-0.12.10-nullsafety.1/lib/
meta:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/meta-1.3.0-nullsafety.3/lib/
mockito:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/mockito-4.1.4/lib/
node_interop:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/node_interop-1.2.1/lib/
node_io:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/node_io-1.1.1/lib/
package_config:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/package_config-1.9.3/lib/
path:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/path-1.8.0-nullsafety.1/lib/
pedantic:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/pedantic-1.9.2/lib/
platform:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/platform-3.0.0-nullsafety.2/lib/
plugin_platform_interface:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/plugin_platform_interface-1.0.3/lib/
process:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/process-4.0.0-nullsafety.2/lib/
pub_semver:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/pub_semver-1.4.4/lib/
quiver:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/quiver-2.1.5/lib/
sky_engine:file:///D:/dev/flutter/bin/cache/pkg/sky_engine/lib/
source_gen:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/source_gen-0.9.10+3/lib/
source_span:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/source_span-1.8.0-nullsafety.2/lib/
stack_trace:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/stack_trace-1.10.0-nullsafety.1/lib/
stream_channel:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/stream_channel-2.1.0-nullsafety.1/lib/
string_scanner:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/string_scanner-1.1.0-nullsafety.1/lib/
sync_http:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/sync_http-0.2.0/lib/
term_glyph:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/term_glyph-1.2.0-nullsafety.1/lib/
test_api:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/test_api-0.2.19-nullsafety.2/lib/
typed_data:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/typed_data-1.3.0-nullsafety.3/lib/
url_launcher:../lib/
url_launcher_linux:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/url_launcher_linux-0.0.1+4/lib/
url_launcher_macos:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/url_launcher_macos-0.0.1+9/lib/
url_launcher_platform_interface:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/url_launcher_platform_interface-1.0.9/lib/
url_launcher_web:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/url_launcher_web-0.1.5+3/lib/
url_launcher_windows:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/url_launcher_windows-0.0.1+3/lib/
vector_math:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/vector_math-2.1.0-nullsafety.3/lib/
vm_service_client:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/vm_service_client-0.2.6+2/lib/
watcher:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/watcher-0.9.7+15/lib/
web_socket_channel:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/web_socket_channel-1.1.0/lib/
webdriver:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/webdriver-2.1.2/lib/
yaml:file:///C:/Users/qiaomeng/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/yaml-2.2.1/lib/
url_launcher_example:lib/
# url_launcher_example
Demonstrates how to use the url_launcher plugin.
## Getting Started
For help getting started with Flutter, view our online
[documentation](https://flutter.dev/).
#Tue Mar 16 10:12:34 CST 2021
gradle.version=5.1.1
# Default ignored files
/shelf/
/workspace.xml
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="1.8" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="PLATFORM" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="1.8 (2)" />
<option name="modules">
<set>
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/url_launcher_linux-0.0.1+4/android" />
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/url_launcher_macos-0.0.1+9/android" />
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/url_launcher_web-0.1.5+3/android" />
<option value="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/url_launcher_windows-0.0.1+3/android" />
<option value="$PROJECT_DIR$/../../android" />
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
<option name="useQualifiedModuleNames" value="true" />
</GradleProjectSettings>
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven3" />
<option name="name" value="maven3" />
<option name="url" value="https://mirrors.tuna.tsinghua.edu.cn/flutter/download.flutter.io" />
</remote-repository>
<remote-repository>
<option name="id" value="BintrayJCenter2" />
<option name="name" value="BintrayJCenter2" />
<option name="url" value="https://jcenter.bintray.com/" />
</remote-repository>
<remote-repository>
<option name="id" value="Google2" />
<option name="name" value="Google2" />
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
</remote-repository>
</component>
</project>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: ./../build/app/intermediates/flutter/debug/libs.jar">
<CLASSES>
<root url="jar://$PROJECT_DIR$/../build/app/intermediates/flutter/debug/libs.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: androidx.activity:activity:1.0.0@aar">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/4de50886b54a45d98bd144547d690898/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/4de50886b54a45d98bd144547d690898/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/4de50886b54a45d98bd144547d690898/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.activity/activity/1.0.0/28eb83e6a29ac3fbb87aa632cfa0e644a313f491/activity-1.0.0-sources.jar!/" />
</SOURCES>
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: androidx.annotation:annotation:1.1.0">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.annotation/annotation/1.1.0/e3a6fb2f40e3a3842e6b7472628ba4ce416ea4c8/annotation-1.1.0.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.annotation/annotation/1.1.0/408af38ec57369afe3fd6466e1c4bfdd5f15fc92/annotation-1.1.0-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.annotation/annotation/1.1.0/8b7bdc00eb4d998bfbc76767b098620990f2a805/annotation-1.1.0-sources.jar!/" />
</SOURCES>
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: androidx.arch.core:core-common:2.1.0">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.arch.core/core-common/2.1.0/b3152fc64428c9354344bd89848ecddc09b6f07e/core-common-2.1.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.arch.core/core-common/2.1.0/80ac2d7c8e6400ce2fbc663cd1a7e1cbef38c4b8/core-common-2.1.0-sources.jar!/" />
</SOURCES>
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: androidx.arch.core:core-runtime:2.0.0@aar">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/8f9a0a2cc554cadd1f2f04087cac05fb/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/8f9a0a2cc554cadd1f2f04087cac05fb/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/8f9a0a2cc554cadd1f2f04087cac05fb/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.arch.core/core-runtime/2.0.0/bc41b287c95bc50a3cd27cb1b7cfb301805ba7f1/core-runtime-2.0.0-sources.jar!/" />
</SOURCES>
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: androidx.collection:collection:1.1.0">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.collection/collection/1.1.0/1f27220b47669781457de0d600849a5de0e89909/collection-1.1.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.collection/collection/1.1.0/bae67b0019fbb38498198fcc2d0282a340b71c5b/collection-1.1.0-sources.jar!/" />
</SOURCES>
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: androidx.core:core:1.1.0@aar">
<ANNOTATIONS>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/60097d4f898b7ca10f95c8bc18f64a6f/annotations.zip!/" />
</ANNOTATIONS>
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/60097d4f898b7ca10f95c8bc18f64a6f/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/60097d4f898b7ca10f95c8bc18f64a6f/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/60097d4f898b7ca10f95c8bc18f64a6f/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.core/core/1.1.0/4ae37fad1fe95b42aa47a720908df37ba5d3c85e/core-1.1.0-sources.jar!/" />
</SOURCES>
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: androidx.customview:customview:1.0.0@aar">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/4db461d735f03e828a775300339215d3/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/4db461d735f03e828a775300339215d3/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/4db461d735f03e828a775300339215d3/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.customview/customview/1.0.0/61f6a717d144dff3a6bda413d9abeeb2bca71581/customview-1.0.0-sources.jar!/" />
</SOURCES>
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: androidx.fragment:fragment:1.1.0@aar">
<ANNOTATIONS>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/46b115632576266be3ed16a8648b1b02/annotations.zip!/" />
</ANNOTATIONS>
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/46b115632576266be3ed16a8648b1b02/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/46b115632576266be3ed16a8648b1b02/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/46b115632576266be3ed16a8648b1b02/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.fragment/fragment/1.1.0/b9ebb04df2cb0cad4419af3c658690bc82aa5706/fragment-1.1.0-sources.jar!/" />
</SOURCES>
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: androidx.lifecycle:lifecycle-common:2.2.0">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.lifecycle/lifecycle-common/2.2.0/4ef09a745007778eef83b92f8f23987a8ea59496/lifecycle-common-2.2.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.lifecycle/lifecycle-common/2.2.0/d38861c5e1656c5eb1890b1fa149510f38aa5d42/lifecycle-common-2.2.0-sources.jar!/" />
</SOURCES>
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: androidx.lifecycle:lifecycle-common-java8:2.2.0">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.lifecycle/lifecycle-common-java8/2.2.0/cd3478503da69b1a7e0319bd2d1389943db9b364/lifecycle-common-java8-2.2.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.lifecycle/lifecycle-common-java8/2.2.0/777ad8a2c39ec412a8c77a3923ceb536946acb29/lifecycle-common-java8-2.2.0-sources.jar!/" />
</SOURCES>
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: androidx.lifecycle:lifecycle-livedata:2.0.0@aar">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/898998f9d0108858b7e12bcd765c6a76/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/898998f9d0108858b7e12bcd765c6a76/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/898998f9d0108858b7e12bcd765c6a76/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.lifecycle/lifecycle-livedata/2.0.0/740ce61935bd789380c01178bd8ce402402ebd2f/lifecycle-livedata-2.0.0-sources.jar!/" />
</SOURCES>
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: androidx.lifecycle:lifecycle-livedata-core:2.0.0@aar">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/29746787bad6451bbaa4a3ff44779546/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/29746787bad6451bbaa4a3ff44779546/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/29746787bad6451bbaa4a3ff44779546/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.lifecycle/lifecycle-livedata-core/2.0.0/c158207594782b42f3a2e08a5a029eb3319e4404/lifecycle-livedata-core-2.0.0-sources.jar!/" />
</SOURCES>
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: androidx.lifecycle:lifecycle-runtime:2.2.0@aar">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/43bcdada84e6bd7826860912db3310b6/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/43bcdada84e6bd7826860912db3310b6/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/43bcdada84e6bd7826860912db3310b6/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.lifecycle/lifecycle-runtime/2.2.0/bac4e407cc35ca0fcd4c3c18d699fa632475b019/lifecycle-runtime-2.2.0-sources.jar!/" />
</SOURCES>
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: androidx.lifecycle:lifecycle-viewmodel:2.1.0@aar">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/c6f281fa249a633fe41363d646a54e86/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/c6f281fa249a633fe41363d646a54e86/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/c6f281fa249a633fe41363d646a54e86/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.lifecycle/lifecycle-viewmodel/2.1.0/bfd86b9887c2343516f82bed91acbab34a45841d/lifecycle-viewmodel-2.1.0-sources.jar!/" />
</SOURCES>
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: androidx.loader:loader:1.0.0@aar">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/8be28c36cc59055013a3e7b1cf9b9611/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/8be28c36cc59055013a3e7b1cf9b9611/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/8be28c36cc59055013a3e7b1cf9b9611/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.loader/loader/1.0.0/b9ef587f3e46c7fe5b00264989764e43ff45cada/loader-1.0.0-sources.jar!/" />
</SOURCES>
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: androidx.savedstate:savedstate:1.0.0@aar">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/94bf9fd34921bdc9b817ad3cb0af8ac7/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/94bf9fd34921bdc9b817ad3cb0af8ac7/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/94bf9fd34921bdc9b817ad3cb0af8ac7/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.savedstate/savedstate/1.0.0/e6daf87ed227a6f80bb8accb466755a5ee01a652/savedstate-1.0.0-sources.jar!/" />
</SOURCES>
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: androidx.test:core:1.0.0@aar">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/66526cf3c877d8418ad3c7297e647e81/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/66526cf3c877d8418ad3c7297e647e81/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/66526cf3c877d8418ad3c7297e647e81/AndroidManifest.xml" />
</CLASSES>
<JAVADOC>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.test/core/1.0.0/fb3d5e80a838f741ea0f7c223c127efbc9fc4ada/core-1.0.0-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.test/core/1.0.0/6406894ea7a0bc3887f6ccf47bf58a56e9217cb6/core-1.0.0-sources.jar!/" />
</SOURCES>
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: androidx.test:monitor:1.1.0@aar">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/d09c5250e479e7871c95014f731f656b/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/d09c5250e479e7871c95014f731f656b/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/d09c5250e479e7871c95014f731f656b/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.test/monitor/1.1.0/d5021e13cb13f510b6d876a591a7eb9f33d52688/monitor-1.1.0-sources.jar!/" />
</SOURCES>
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: androidx.versionedparcelable:versionedparcelable:1.1.0@aar">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/cf8b72ef40837c4a3c7fc808bad6b980/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/cf8b72ef40837c4a3c7fc808bad6b980/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/cf8b72ef40837c4a3c7fc808bad6b980/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.versionedparcelable/versionedparcelable/1.1.0/d9085927216387af679d18b6f472bc0fc5c7cc81/versionedparcelable-1.1.0-sources.jar!/" />
</SOURCES>
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: androidx.viewpager:viewpager:1.0.0@aar">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/c02f5e5e09cd384c115b82e009a25de2/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/c02f5e5e09cd384c115b82e009a25de2/res" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-2/files-2.1/c02f5e5e09cd384c115b82e009a25de2/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/androidx.viewpager/viewpager/1.0.0/db045f92188b9d247d5f556866f8861ab68528f0/viewpager-1.0.0-sources.jar!/" />
</SOURCES>
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: io.flutter:arm64_v8a_debug:1.0.0-2c956a31c0a3d350827aee6c56bb63337c5b4e6e">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/io.flutter/arm64_v8a_debug/1.0.0-2c956a31c0a3d350827aee6c56bb63337c5b4e6e/caf4bb9beec91fb690037b6b81d58ec7f54cc3d3/arm64_v8a_debug-1.0.0-2c956a31c0a3d350827aee6c56bb63337c5b4e6e.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: io.flutter:armeabi_v7a_debug:1.0.0-2c956a31c0a3d350827aee6c56bb63337c5b4e6e">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/io.flutter/armeabi_v7a_debug/1.0.0-2c956a31c0a3d350827aee6c56bb63337c5b4e6e/627724bf9606793d930ab87b5496ea4703b07b40/armeabi_v7a_debug-1.0.0-2c956a31c0a3d350827aee6c56bb63337c5b4e6e.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: io.flutter:flutter_embedding_debug:1.0.0-2c956a31c0a3d350827aee6c56bb63337c5b4e6e">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/io.flutter/flutter_embedding_debug/1.0.0-2c956a31c0a3d350827aee6c56bb63337c5b4e6e/d766fe2feb740ead017d002eae7d82dd4f337a93/flutter_embedding_debug-1.0.0-2c956a31c0a3d350827aee6c56bb63337c5b4e6e.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/io.flutter/flutter_embedding_debug/1.0.0-2c956a31c0a3d350827aee6c56bb63337c5b4e6e/deb466af784895bc1a2f24da6b05aac8bb88f6b4/flutter_embedding_debug-1.0.0-2c956a31c0a3d350827aee6c56bb63337c5b4e6e-sources.jar!/" />
</SOURCES>
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: io.flutter:x86_64_debug:1.0.0-2c956a31c0a3d350827aee6c56bb63337c5b4e6e">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/io.flutter/x86_64_debug/1.0.0-2c956a31c0a3d350827aee6c56bb63337c5b4e6e/eb0cf19997744cadd524699414821a128b3e10bc/x86_64_debug-1.0.0-2c956a31c0a3d350827aee6c56bb63337c5b4e6e.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Gradle: io.flutter:x86_debug:1.0.0-2c956a31c0a3d350827aee6c56bb63337c5b4e6e">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/io.flutter/x86_debug/1.0.0-2c956a31c0a3d350827aee6c56bb63337c5b4e6e/9de6a21df971ba38e99d827ddaa4b269782308b1/x86_debug-1.0.0-2c956a31c0a3d350827aee6c56bb63337c5b4e6e.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/modules/android.iml" filepath="$PROJECT_DIR$/.idea/modules/android.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/app/android.app.iml" filepath="$PROJECT_DIR$/.idea/modules/app/android.app.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/1393079023/android.url_launcher.iml" filepath="$PROJECT_DIR$/.idea/modules/1393079023/android.url_launcher.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/-852728612/android.url_launcher_linux.iml" filepath="$PROJECT_DIR$/.idea/modules/-852728612/android.url_launcher_linux.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/2097020000/android.url_launcher_macos.iml" filepath="$PROJECT_DIR$/.idea/modules/2097020000/android.url_launcher_macos.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/-1246178432/android.url_launcher_web.iml" filepath="$PROJECT_DIR$/.idea/modules/-1246178432/android.url_launcher_web.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/-1845139542/android.url_launcher_windows.iml" filepath="$PROJECT_DIR$/.idea/modules/-1845139542/android.url_launcher_windows.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":url_launcher_web" external.linked.project.path="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/url_launcher_web-0.1.5+3/android" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="android" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":url_launcher_web" />
<option name="LAST_SUCCESSFUL_SYNC_AGP_VERSION" />
<option name="LAST_KNOWN_AGP_VERSION" />
</configuration>
</facet>
<facet type="java-gradle" name="Java-Gradle">
<configuration>
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/../../../../build/url_launcher_web" />
<option name="BUILDABLE" value="false" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/url_launcher_web-0.1.5+3/android">
<excludeFolder url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/url_launcher_web-0.1.5+3/android/.gradle" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":url_launcher_windows" external.linked.project.path="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/url_launcher_windows-0.0.1+3/android" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="android" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":url_launcher_windows" />
<option name="LAST_SUCCESSFUL_SYNC_AGP_VERSION" />
<option name="LAST_KNOWN_AGP_VERSION" />
</configuration>
</facet>
<facet type="java-gradle" name="Java-Gradle">
<configuration>
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/../../../../build/url_launcher_windows" />
<option name="BUILDABLE" value="false" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/url_launcher_windows-0.0.1+3/android">
<excludeFolder url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/url_launcher_windows-0.0.1+3/android/.gradle" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":url_launcher_linux" external.linked.project.path="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/url_launcher_linux-0.0.1+4/android" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="android" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":url_launcher_linux" />
<option name="LAST_SUCCESSFUL_SYNC_AGP_VERSION" />
<option name="LAST_KNOWN_AGP_VERSION" />
</configuration>
</facet>
<facet type="java-gradle" name="Java-Gradle">
<configuration>
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/../../../../build/url_launcher_linux" />
<option name="BUILDABLE" value="false" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/url_launcher_linux-0.0.1+4/android">
<excludeFolder url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/url_launcher_linux-0.0.1+4/android/.gradle" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":url_launcher" external.linked.project.path="$MODULE_DIR$/../../../../../android" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="io.flutter.plugins.urllauncher" external.system.module.version="1.0-SNAPSHOT" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":url_launcher" />
<option name="LAST_SUCCESSFUL_SYNC_AGP_VERSION" value="3.4.2" />
<option name="LAST_KNOWN_AGP_VERSION" value="3.4.2" />
</configuration>
</facet>
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="debug" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<afterSyncTasks>
<task>generateDebugSources</task>
</afterSyncTasks>
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/../../../../../android/src/main/res;file://$MODULE_DIR$/../../../../../android/src/debug/res;file://$MODULE_DIR$/../../../../build/url_launcher/generated/res/rs/debug;file://$MODULE_DIR$/../../../../build/url_launcher/generated/res/resValues/debug" />
<option name="TEST_RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/../../../../../android/src/androidTest/res;file://$MODULE_DIR$/../../../../../android/src/androidTestDebug/res;file://$MODULE_DIR$/../../../../build/url_launcher/generated/res/rs/androidTest/debug;file://$MODULE_DIR$/../../../../build/url_launcher/generated/res/resValues/androidTest/debug" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
<option name="PROJECT_TYPE" value="1" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7">
<output url="file://$MODULE_DIR$/../../../../build/url_launcher/intermediates/javac/debug/compileDebugJavaWithJavac/classes" />
<output-test url="file://$MODULE_DIR$/../../../../build/url_launcher/intermediates/javac/debugUnitTest/compileDebugUnitTestJavaWithJavac/classes" />
<exclude-output />
<content url="file://$MODULE_DIR$/../../../../../android">
<sourceFolder url="file://$MODULE_DIR$/../../../../../android/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../../../../android/src/test/java" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/../../../../../android/.gradle" />
</content>
<content url="file://$MODULE_DIR$/../../../../build/url_launcher/generated/aidl_source_output_dir/debug/compileDebugAidl/out" />
<content url="file://$MODULE_DIR$/../../../../build/url_launcher/generated/aidl_source_output_dir/debugAndroidTest/compileDebugAndroidTestAidl/out" />
<content url="file://$MODULE_DIR$/../../../../build/url_launcher/generated/renderscript_source_output_dir/debug/compileDebugRenderscript/out" />
<content url="file://$MODULE_DIR$/../../../../build/url_launcher/generated/renderscript_source_output_dir/debugAndroidTest/compileDebugAndroidTestRenderscript/out" />
<content url="file://$MODULE_DIR$/../../../../build/url_launcher/generated/res/resValues/androidTest/debug" />
<content url="file://$MODULE_DIR$/../../../../build/url_launcher/generated/res/resValues/debug" />
<content url="file://$MODULE_DIR$/../../../../build/url_launcher/generated/res/rs/androidTest/debug" />
<content url="file://$MODULE_DIR$/../../../../build/url_launcher/generated/res/rs/debug" />
<content url="file://$MODULE_DIR$/../../../../build/url_launcher/generated/source/apt/androidTest/debug" />
<content url="file://$MODULE_DIR$/../../../../build/url_launcher/generated/source/apt/debug" />
<content url="file://$MODULE_DIR$/../../../../build/url_launcher/generated/source/apt/test/debug" />
<content url="file://$MODULE_DIR$/../../../../build/url_launcher/generated/source/buildConfig/androidTest/debug" />
<content url="file://$MODULE_DIR$/../../../../build/url_launcher/generated/source/buildConfig/debug" />
<orderEntry type="jdk" jdkName="Android API 29 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Gradle: io.flutter:flutter_embedding_debug:1.0.0-2c956a31c0a3d350827aee6c56bb63337c5b4e6e" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-common-java8:2.2.0" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-common:2.2.0" level="project" />
<orderEntry type="library" name="Gradle: androidx.arch.core:core-common:2.1.0" level="project" />
<orderEntry type="library" name="Gradle: androidx.collection:collection:1.1.0" level="project" />
<orderEntry type="library" name="Gradle: androidx.annotation:annotation:1.1.0" level="project" />
<orderEntry type="library" name="Gradle: androidx.fragment:fragment:1.1.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.activity:activity:1.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.viewpager:viewpager:1.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.loader:loader:1.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.customview:customview:1.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.core:core:1.1.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-runtime:2.2.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.savedstate:savedstate:1.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-livedata:2.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-livedata-core:2.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.arch.core:core-runtime:2.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.versionedparcelable:versionedparcelable:1.1.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-viewmodel:2.1.0@aar" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: androidx.test:core:1.0.0@aar" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: androidx.test:monitor:1.1.0@aar" level="project" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":url_launcher_macos" external.linked.project.path="$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/url_launcher_macos-0.0.1+9/android" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="android" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":url_launcher_macos" />
<option name="LAST_SUCCESSFUL_SYNC_AGP_VERSION" />
<option name="LAST_KNOWN_AGP_VERSION" />
</configuration>
</facet>
<facet type="java-gradle" name="Java-Gradle">
<configuration>
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/../../../../build/url_launcher_macos" />
<option name="BUILDABLE" value="false" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/url_launcher_macos-0.0.1+9/android">
<excludeFolder url="file://$USER_HOME$/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/url_launcher_macos-0.0.1+9/android/.gradle" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="android" external.linked.project.path="$MODULE_DIR$/../.." external.root.project.path="$MODULE_DIR$/../.." external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="java-gradle" name="Java-Gradle">
<configuration>
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/../../../build" />
<option name="BUILDABLE" value="false" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$/../..">
<excludeFolder url="file://$MODULE_DIR$/../../.gradle" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$/../../../app" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="android" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":app" />
<option name="LAST_SUCCESSFUL_SYNC_AGP_VERSION" value="3.4.2" />
<option name="LAST_KNOWN_AGP_VERSION" value="3.4.2" />
</configuration>
</facet>
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="debug" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<afterSyncTasks>
<task>generateDebugSources</task>
</afterSyncTasks>
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/../../../app/src/main/res;file://$MODULE_DIR$/../../../app/src/debug/res;file://$MODULE_DIR$/../../../../build/app/generated/res/rs/debug;file://$MODULE_DIR$/../../../../build/app/generated/res/resValues/debug" />
<option name="TEST_RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/../../../app/src/androidTest/res;file://$MODULE_DIR$/../../../app/src/androidTestDebug/res;file://$MODULE_DIR$/../../../../build/app/generated/res/rs/androidTest/debug;file://$MODULE_DIR$/../../../../build/app/generated/res/resValues/androidTest/debug" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/../../../../build/app/intermediates/javac/debug/compileDebugJavaWithJavac/classes" />
<output-test url="file://$MODULE_DIR$/../../../../build/app/intermediates/javac/debugUnitTest/compileDebugUnitTestJavaWithJavac/classes" />
<exclude-output />
<content url="file://$MODULE_DIR$/../../../app">
<sourceFolder url="file://$MODULE_DIR$/../../../app/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../../app/src/androidTestDebug/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/../../../app/src/main/res" type="java-resource" />
<excludeFolder url="file://$MODULE_DIR$/../../../app/.gradle" />
</content>
<content url="file://$MODULE_DIR$/../../../../build/app/generated/aidl_source_output_dir/debug/compileDebugAidl/out" />
<content url="file://$MODULE_DIR$/../../../../build/app/generated/aidl_source_output_dir/debugAndroidTest/compileDebugAndroidTestAidl/out" />
<content url="file://$MODULE_DIR$/../../../../build/app/generated/renderscript_source_output_dir/debug/compileDebugRenderscript/out" />
<content url="file://$MODULE_DIR$/../../../../build/app/generated/renderscript_source_output_dir/debugAndroidTest/compileDebugAndroidTestRenderscript/out" />
<content url="file://$MODULE_DIR$/../../../../build/app/generated/res/resValues/androidTest/debug" />
<content url="file://$MODULE_DIR$/../../../../build/app/generated/res/resValues/debug" />
<content url="file://$MODULE_DIR$/../../../../build/app/generated/res/rs/androidTest/debug" />
<content url="file://$MODULE_DIR$/../../../../build/app/generated/res/rs/debug" />
<content url="file://$MODULE_DIR$/../../../../build/app/generated/source/apt/androidTest/debug" />
<content url="file://$MODULE_DIR$/../../../../build/app/generated/source/apt/debug" />
<content url="file://$MODULE_DIR$/../../../../build/app/generated/source/apt/test/debug" />
<content url="file://$MODULE_DIR$/../../../../build/app/generated/source/buildConfig/androidTest/debug" />
<content url="file://$MODULE_DIR$/../../../../build/app/generated/source/buildConfig/debug" />
<orderEntry type="jdk" jdkName="Android API 29 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Gradle: ./../build/app/intermediates/flutter/debug/libs.jar" level="project" />
<orderEntry type="library" name="Gradle: io.flutter:flutter_embedding_debug:1.0.0-2c956a31c0a3d350827aee6c56bb63337c5b4e6e" level="project" />
<orderEntry type="library" name="Gradle: io.flutter:armeabi_v7a_debug:1.0.0-2c956a31c0a3d350827aee6c56bb63337c5b4e6e" level="project" />
<orderEntry type="library" name="Gradle: io.flutter:arm64_v8a_debug:1.0.0-2c956a31c0a3d350827aee6c56bb63337c5b4e6e" level="project" />
<orderEntry type="library" name="Gradle: io.flutter:x86_64_debug:1.0.0-2c956a31c0a3d350827aee6c56bb63337c5b4e6e" level="project" />
<orderEntry type="library" name="Gradle: io.flutter:x86_debug:1.0.0-2c956a31c0a3d350827aee6c56bb63337c5b4e6e" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-common-java8:2.2.0" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-common:2.2.0" level="project" />
<orderEntry type="library" name="Gradle: androidx.arch.core:core-common:2.1.0" level="project" />
<orderEntry type="library" name="Gradle: androidx.collection:collection:1.1.0" level="project" />
<orderEntry type="library" name="Gradle: androidx.annotation:annotation:1.1.0" level="project" />
<orderEntry type="library" name="Gradle: androidx.fragment:fragment:1.1.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.activity:activity:1.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.viewpager:viewpager:1.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.loader:loader:1.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.customview:customview:1.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.core:core:1.1.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-runtime:2.2.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.savedstate:savedstate:1.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-livedata:2.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-livedata-core:2.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.arch.core:core-runtime:2.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.versionedparcelable:versionedparcelable:1.1.0@aar" level="project" />
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-viewmodel:2.1.0@aar" level="project" />
<orderEntry type="module" module-name="android.url_launcher" />
</component>
</module>
\ No newline at end of file
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 29
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
applicationId "io.flutter.plugins.urllauncherexample"
minSdkVersion 16
targetSdkVersion 28
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}
flutter {
source '../..'
}
dependencies {
// testImplementation 'junit:junit:4.12'
// androidTestImplementation 'androidx.test:runner:1.2.0'
// androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
package io.flutter.plugins.urllauncherexample;
import androidx.test.rule.ActivityTestRule;
import dev.flutter.plugins.integration_test.FlutterTestRunner;
import org.junit.Rule;
import org.junit.runner.RunWith;
@RunWith(FlutterTestRunner.class)
@SuppressWarnings("deprecation")
public class EmbeddingV1ActivityTest {
@Rule
public ActivityTestRule<EmbeddingV1Activity> rule =
new ActivityTestRule<>(EmbeddingV1Activity.class);
}
package io.flutter.plugins.urllauncherexample;
import androidx.test.rule.ActivityTestRule;
import dev.flutter.plugins.integration_test.FlutterTestRunner;
import io.flutter.embedding.android.FlutterActivity;
import org.junit.Rule;
import org.junit.runner.RunWith;
@RunWith(FlutterTestRunner.class)
public class FlutterActivityTest {
@Rule
public ActivityTestRule<FlutterActivity> rule = new ActivityTestRule<>(FlutterActivity.class);
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.flutter.plugins.urllauncherexample">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:icon="@mipmap/ic_launcher"
android:label="url_launcher_example"
android:name="io.flutter.app.FlutterApplication">
<activity
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
android:hardwareAccelerated="true"
android:exported="true"
android:name="io.flutter.plugins.urllauncherexample.EmbeddingV1Activity"
android:theme="@android:style/Theme.Black.NoTitleBar"
android:windowSoftInputMode="adjustResize">
</activity>
<activity
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
android:hardwareAccelerated="true"
android:name="io.flutter.embedding.android.FlutterActivity"
android:theme="@android:style/Theme.Black.NoTitleBar"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<meta-data android:name="flutterEmbedding" android:value="2"/>
</application>
<!-- The INTERNET permission is required for development. Specifically,
flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
package io.flutter.plugins;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import io.flutter.embedding.engine.FlutterEngine;
/**
* Generated file. Do not edit.
* This file is generated by the Flutter tool based on the
* plugins that support the Android platform.
*/
@Keep
public final class GeneratedPluginRegistrant {
public static void registerWith(@NonNull FlutterEngine flutterEngine) {
flutterEngine.getPlugins().add(new io.flutter.plugins.urllauncher.UrlLauncherPlugin());
}
}
// 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.urllauncherexample;
import android.os.Bundle;
import dev.flutter.plugins.integration_test.IntegrationTestPlugin;
import io.flutter.plugins.urllauncher.UrlLauncherPlugin;
@SuppressWarnings("deprecation")
public class EmbeddingV1Activity extends io.flutter.app.FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
IntegrationTestPlugin.registerWith(
registrarFor("dev.flutter.plugins.integration_test.IntegrationTestPlugin"));
UrlLauncherPlugin.registerWith(
registrarFor("io.flutter.plugins.urllauncher.UrlLauncherPlugin"));
}
}
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.2'
}
}
allprojects {
repositories {
google()
jcenter()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
android.enableR8=true
#Wed Jul 31 20:16:04 BRT 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
sdk.dir=D:\\dev\\androidSdk
flutter.sdk=D:\\dev\\flutter
\ No newline at end of file
include ':app'
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
pluginsFile.withInputStream { stream -> plugins.load(stream) }
}
plugins.each { name, path ->
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
include ":$name"
project(":$name").projectDir = pluginDirectory
}
<?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>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>arm64</string>
</array>
<key>MinimumOSVersion</key>
<string>8.0</string>
</dict>
</plist>
#include "Generated.xcconfig"
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
// This is a generated file; do not edit or check into version control.
FLUTTER_ROOT=D:\dev\flutter
FLUTTER_APPLICATION_PATH=D:\android_project\url_launcher\example
FLUTTER_TARGET=lib\main.dart
FLUTTER_BUILD_DIR=build
SYMROOT=${SOURCE_ROOT}/../build\ios
OTHER_LDFLAGS=$(inherited) -framework Flutter
FLUTTER_FRAMEWORK_DIR=D:\dev\flutter\bin\cache\artifacts\engine\ios
FLUTTER_BUILD_NAME=1.0.0
FLUTTER_BUILD_NUMBER=1
DART_OBFUSCATION=false
TRACK_WIDGET_CREATION=false
TREE_SHAKE_ICONS=false
PACKAGE_CONFIG=.packages
#include "Generated.xcconfig"
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=D:\dev\flutter"
export "FLUTTER_APPLICATION_PATH=D:\android_project\url_launcher\example"
export "FLUTTER_TARGET=lib\main.dart"
export "FLUTTER_BUILD_DIR=build"
export "SYMROOT=${SOURCE_ROOT}/../build\ios"
export "OTHER_LDFLAGS=$(inherited) -framework Flutter"
export "FLUTTER_FRAMEWORK_DIR=D:\dev\flutter\bin\cache\artifacts\engine\ios"
export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1"
export "DART_OBFUSCATION=false"
export "TRACK_WIDGET_CREATION=false"
export "TREE_SHAKE_ICONS=false"
export "PACKAGE_CONFIG=.packages"
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1100"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>
// 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 <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
@interface AppDelegate : FlutterAppDelegate
@end
// 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.
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GeneratedPluginRegistrant registerWithRegistry:self];
[super application:application didFinishLaunchingWithOptions:launchOptions];
return YES;
}
@end
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment