blob: c3a563a9c137a448e68acb3904971bec3b0191b4 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package io.flutter.plugins.urllauncher;
import android.app.Activity;
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 android.util.Log;
import androidx.annotation.Nullable;
/** Launches components for URLs. */
class UrlLauncher {
private static final String TAG = "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());
if (componentName == null) {
Log.i(TAG, "component name for " + url + " is null");
return false;
} else {
Log.i(TAG, "component name for " + url + " is " + componentName.toShortString());
return !"{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 (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);
}
try {
activity.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,
}
}