This repository has been archived by the owner on Feb 22, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 9.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[url_launcher] Re-land v2 embedding support (#2204)
This is identical to the original PR, except it correctly increments the Flutter SDK version to the latest stable and fixes some minor Java style nits.
- Loading branch information
Michael Klimushyn
committed
Oct 17, 2019
1 parent
3e271bc
commit 2951f84
Showing
18 changed files
with
556 additions
and
124 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
packages/url_launcher/url_launcher/android/src/main/AndroidManifest.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
113 changes: 113 additions & 0 deletions
113
..._launcher/android/src/main/java/io/flutter/plugins/urllauncher/MethodCallHandlerImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
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 { | ||
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; | ||
} | ||
} |
91 changes: 91 additions & 0 deletions
91
...uncher/url_launcher/android/src/main/java/io/flutter/plugins/urllauncher/UrlLauncher.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package io.flutter.plugins.urllauncher; | ||
|
||
import android.app.Activity; | ||
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.Nullable; | ||
|
||
/** Launches components for URLs. */ | ||
class UrlLauncher { | ||
private final Context applicationContext; | ||
@Nullable private Activity activity; | ||
|
||
/** | ||
* 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.activity = activity; | ||
} | ||
|
||
void setActivity(@Nullable Activity activity) { | ||
this.activity = activity; | ||
} | ||
|
||
/** 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#OK} otherwise. | ||
*/ | ||
LaunchStatus launch( | ||
String url, | ||
Bundle headersBundle, | ||
boolean useWebView, | ||
boolean enableJavaScript, | ||
boolean enableDomStorage) { | ||
if (activity == null) { | ||
return LaunchStatus.NO_ACTIVITY; | ||
} | ||
|
||
Intent launchIntent; | ||
if (useWebView) { | ||
launchIntent = | ||
WebViewActivity.createIntent( | ||
activity, url, enableJavaScript, enableDomStorage, headersBundle); | ||
} else { | ||
launchIntent = | ||
new Intent(Intent.ACTION_VIEW) | ||
.setData(Uri.parse(url)) | ||
.putExtra(Browser.EXTRA_HEADERS, headersBundle); | ||
} | ||
|
||
activity.startActivity(launchIntent); | ||
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, | ||
} | ||
} |
Oops, something went wrong.