我基于PWABuilder开发了一个Trusted Web Activity,并且已经部署在Play Store上,但是当我已经登录时,正确的行为将重定向到仪表板(我使用window.location.assign('/ dashboard' )),但TWA尝试启动浏览器活动,如何防止此行为?并保持页面流在TWA中?下一个屏幕截图显示了如何尝试打开浏览器:
AndroidManifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="miretail.com.pwa">
<supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:resizeable="true" android:smallScreens="true" android:xlargeScreens="true" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:label="@string/app_name"
android:allowBackup="true"
android:supportsRtl="true"
android:icon="@mipmap/ic_launcher"
android:theme="@style/SplashTheme"
tools:ignore="GoogleAppIndexingWarning" >
<meta-data
android:name="asset_statements"
android:resource="@string/asset_statements" />
<activity android:name="miretail.com.pwa.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="android.support.customtabs.trusted.LauncherActivity">
<!-- Edit android:value to change the url opened by the TWA -->
<meta-data
android:name="android.support.customtabs.trusted.DEFAULT_URL"
android:value="@string/app_url" />
<!-- This intent-filter adds the TWA to the Android Launcher -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!--
This intent-filter allows the TWA to handle Intents to open
airhorner.com.
-->
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE"/>
<!-- Edit android:host to handle links to the target URL-->
<data
android:scheme="https"
android:host="@string/app_host"/>
</intent-filter>
</activity>
</application>
</manifest>
manifest.json:
{
"dir": "ltr",
"lang": "en-us",
"name": "Mi Retail",
"scope": "https://app.miretail.com.co/*/*",
"display": "standalone",
"start_url": "https://app.miretail.com.co/login",
"short_name": "Mi Retail",
"theme_color": "transparent",
"description": "GROW YOUR RETAIL WITH MI RETAIL. Effortlessly sell, manage, report and grow your retail business in every way with Mi Retail unmatched POS, multi-outlet retail and inventory management system.",
"orientation": "any",
"background_color": "transparent",
"related_applications": [],
"prefer_related_applications": false,
"icons": []
}
MainActivity.java:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loadManifest();
setDisplay(this);
setOrientation(this);
setName(this);
setContentView(R.layout.activity_main);
setWebView((WebView) this.findViewById(R.id.webView));
}
private void setDisplay(Activity activity) {
if (this.manifestObject.optString("display").equals("fullscreen")) {
activity.setTheme(R.style.FullscreenTheme);
} else {
activity.setTheme(R.style.AppTheme);
}
}
private void setName(Activity activity) {
String name = this.manifestObject.optString("name");
if (!name.isEmpty()) {
activity.setTitle(name);
}
}
private static final String ANY = "any";
private static final String NATURAL = "natural";
private static final String PORTRAIT_PRIMARY = "portrait-primary";
private static final String PORTRAIT_SECONDARY = "portrait-secondary";
private static final String LANDSCAPE_PRIMARY = "landscape-primary";
private static final String LANDSCAPE_SECONDARY = "landscape-secondary";
private static final String PORTRAIT = "portrait";
private static final String LANDSCAPE = "landscape";
private void setOrientation(Activity activity) {
String orientation = this.manifestObject.optString("orientation");
switch (orientation) {
case LANDSCAPE_PRIMARY:
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
break;
case PORTRAIT_PRIMARY:
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
break;
case LANDSCAPE:
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
break;
case PORTRAIT:
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
break;
case LANDSCAPE_SECONDARY:
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
break;
case PORTRAIT_SECONDARY:
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
break;
case ANY:
case NATURAL:
default:
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
break;
}
}
@SuppressLint("SetJavaScriptEnabled")
private void setWebView(WebView myWebView) {
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
String start_url = this.manifestObject.optString("start_url");
String scope = this.manifestObject.optString("scope");
myWebView.setWebViewClient(new PwaWebViewClient(start_url, scope));
myWebView.loadUrl(start_url);
}
private static final String DEFAULT_MANIFEST_FILE = "manifest.json";
private JSONObject manifestObject;
private void loadManifest() {
if (this.assetExists((DEFAULT_MANIFEST_FILE))) {
try {
this.manifestObject = this.loadLocalManifest();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
private boolean assetExists(String asset) {
final AssetManager assetManager = this.getResources().getAssets();
try {
return Arrays.asList(assetManager.list("")).contains(asset);
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
private JSONObject loadLocalManifest() throws JSONException {
try {
InputStream inputStream = this.getResources().getAssets().open(DEFAULT_MANIFEST_FILE);
int size = inputStream.available();
byte[] bytes = new byte[size];
int readBytes = inputStream.read(bytes);
inputStream.close();
if (readBytes > 0) {
String jsonString = new String(bytes, "UTF-8");
return new JSONObject(jsonString);
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
还有PWAWebClient.java:
package miretail.com.pwa;
import android.content.Intent;
import android.net.Uri;
import android.webkit.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.regex.Pattern;
class PwaWebViewClient extends WebViewClient {
private Pattern scope_pattern;
public PwaWebViewClient(String start_url, String scope) {
try {
URL baseUrl = new URL(start_url);
URL scopeUrl = new URL(baseUrl, scope);
if (!scopeUrl.toString().endsWith("*")) {
scopeUrl = new URL(scopeUrl, "*");
}
this.scope_pattern = this.regexFromPattern(scopeUrl.toString());
} catch (MalformedURLException e) {
this.scope_pattern = null;
}
}
@SuppressWarnings("deprecation")
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
view.getContext().startActivity(i);
return true;
}
private boolean scoped(String url) {
return this.scope_pattern == null || this.scope_pattern.matcher(url).matches();
}
private Pattern regexFromPattern(String pattern) {
final String toReplace = "\\.[]{}()^$?+|";
StringBuilder regex = new StringBuilder();
for (int i = 0; i < pattern.length(); i++) {
char c = pattern.charAt(i);
if (c == '*') {
regex.append(".");
} else if (toReplace.indexOf(c) > -1) {
regex.append('\\');
}
regex.append(c);
}
return Pattern.compile(regex.toString());
}
}
答案 0 :(得分:0)
您在android:autoVerify
上缺少intent-filter
。有效地添加它会声明您的应用为处理这些URL的默认方式,并且仅在设置了数字资产链接(您必须构建TWA)的情况下有效。
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE"/>
<!-- Edit android:host to handle links to the target URL-->
<data
android:scheme="https"
android:host="@string/app_host"/>
</intent-filter>
如果此更改后仍然发生,请更新此问题。