Trusted Web Activity - 地址栏不隐藏(Chrome for Android 72)
Trusted Web Activity - Address bar not hide (Chrome for Android 72)
我已按照 this 指南学习如何使用受信任的 Web Activity。一切正常,但地址栏仍然出现。一开始我认为这是因为当应用程序正在寻找 assetlinks.json 时,响应是 404。修复它但没有成功删除地址栏。我错过了什么吗?
Chrome版本:72.0.3626.96
Android 版本: 7.1.2 (LineageOS 14.1)
assetlinks.json
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target" : { "namespace": "android_app", "package_name": "com.example.twa_test",
"sha256_cert_fingerprints": ["2A:32:7D:B7:4D:0B:A5:6A:72:47:86:A3:2F:A6:BB:D8:26:DE:AB:7E:8B:EA:C7:16:80:EA:C3:F1:50:E7:8E:D1"] }
}]
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.twa_test">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<meta-data
android:name="asset_statements"
android:resource="@string/asset_statements" />
<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="https://slexom.gitlab.io/namya/" />
<!-- 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="slexom.gitlab.io/namya/" />
</intent-filter>
</activity>
</application>
</manifest>
res/values/strings.xml
<resources>
<string name="app_name">Namya</string>
<string name="asset_statements">
[{
\"relation\": [\"delegate_permission/common.handle_all_urls\"],
\"target\": {
\"namespace\": \"web\",
\"site\": \"https://slexom.gitlab.io/namya/\"}
}]
</string>
</resources>
build.gradle(项目)
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.3.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
maven { url "https://jitpack.io" }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
build.gradle(模块:app)
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.example.twa_test"
minSdkVersion 16
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.github.GoogleChrome.custom-tabs-client:customtabs:3a71a75c9f'
}
Logcat
2019-02-08 18:19:01.918 10880-10880/? I/art: Late-enabling -Xcheck:jni
2019-02-08 18:19:02.352 10880-10880/com.example.twa_test W/System:
ClassLoader referenced unknown path: /data/app/com.example.twa_test-1/lib/arm
2019-02-08 18:19:02.403 10880-10880/com.example.twa_test I/InstantRun:
starting instant run server: is main process
2019-02-08 18:19:02.478 10880-10896/com.example.twa_test D/libEGL: loaded /system/lib/egl/libEGL_mali.so
2019-02-08 18:19:02.510 10880-10896/com.example.twa_test D/libEGL: loaded /system/lib/egl/libGLESv1_CM_mali.so
2019-02-08 18:19:02.660 10880-10880/com.example.twa_test W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
2019-02-08 18:19:02.727 10880-10896/com.example.twa_test D/libEGL: loaded /system/lib/egl/libGLESv2_mali.so
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: Rejecting re-init on previously-failed class java.lang.Class<android.support.v4.view.ViewCompat$OnUnhandledKeyEventListenerWrapper>: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/view/View$OnUnhandledKeyEventListener;
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.support.v4.view.ViewCompat.setBackground(android.view.View, android.graphics.drawable.Drawable) (ViewCompat.java:2341)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.support.v7.widget.ActionBarContainer.<init>(android.content.Context, android.util.AttributeSet) (ActionBarContainer.java:62)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at java.lang.Object java.lang.reflect.Constructor.newInstance0!(java.lang.Object[]) (Constructor.java:-2)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at java.lang.Object java.lang.reflect.Constructor.newInstance(java.lang.Object[]) (Constructor.java:430)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at android.view.View android.view.LayoutInflater.createView(java.lang.String, java.lang.String, android.util.AttributeSet) (LayoutInflater.java:645)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at android.view.View android.view.LayoutInflater.createViewFromTag(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet, boolean) (LayoutInflater.java:787)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at android.view.View android.view.LayoutInflater.createViewFromTag(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet) (LayoutInflater.java:727)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.view.LayoutInflater.rInflate(org.xmlpull.v1.XmlPullParser, android.view.View, android.content.Context, android.util.AttributeSet, boolean) (LayoutInflater.java:858)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.view.LayoutInflater.rInflateChildren(org.xmlpull.v1.XmlPullParser, android.view.View, android.util.AttributeSet, boolean) (LayoutInflater.java:821)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at android.view.View android.view.LayoutInflater.inflate(org.xmlpull.v1.XmlPullParser, android.view.ViewGroup, boolean) (LayoutInflater.java:518)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at android.view.View android.view.LayoutInflater.inflate(int, android.view.ViewGroup, boolean) (LayoutInflater.java:426)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at android.view.View android.view.LayoutInflater.inflate(int, android.view.ViewGroup) (LayoutInflater.java:377)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at android.view.ViewGroup android.support.v7.app.AppCompatDelegateImpl.createSubDecor() (AppCompatDelegateImpl.java:607)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.support.v7.app.AppCompatDelegateImpl.ensureSubDecor() (AppCompatDelegateImpl.java:518)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.support.v7.app.AppCompatDelegateImpl.onPostCreate(android.os.Bundle) (AppCompatDelegateImpl.java:299)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.support.v7.app.AppCompatActivity.onPostCreate(android.os.Bundle) (AppCompatActivity.java:98)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.app.Instrumentation.callActivityOnPostCreate(android.app.Activity, android.os.Bundle) (Instrumentation.java:1200)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at android.app.Activity android.app.ActivityThread.performLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent) (ActivityThread.java:2666)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.app.ActivityThread.handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:2751)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.app.ActivityThread.-wrap12(android.app.ActivityThread, android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:-1)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.app.ActivityThread$H.handleMessage(android.os.Message) (ActivityThread.java:1496)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:102)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.os.Looper.loop() (Looper.java:154)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:6186)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at java.lang.Object java.lang.reflect.Method.invoke!(java.lang.Object, java.lang.Object[]) (Method.java:-2)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run() (ZygoteInit.java:889)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:779)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: Caused by: java.lang.ClassNotFoundException: Didn't find class "android.view.View$OnUnhandledKeyEventListener" on path: DexPathList[[zip file "/data/app/com.example.twa_test-1/base.apk", zip file "/data/app/com.example.twa_test-1/split_lib_dependencies_apk.apk", zip file "/data/app/com.example.twa_test-1/split_lib_slice_0_apk.apk", zip file "/data/app/com.example.twa_test-1/split_lib_slice_1_apk.apk", zip file "/data/app/com.example.twa_test-1/split_lib_slice_2_apk.apk", zip file "/data/app/com.example.twa_test-1/split_lib_slice_3_apk.apk", zip file "/data/app/com.example.twa_test-1/split_lib_slice_4_apk.apk", zip file "/data/app/com.example.twa_test-1/split_lib_slice_5_apk.apk", zip file "/data/app/com.example.twa_test-1/split_lib_slice_6_apk.apk", zip file "/data/app/com.example.twa_test-1/split_lib_slice_7_apk.apk", zip file "/data/app/com.example.twa_test-1/split_lib_slice_8_apk.apk", zip file "/data/app/com.example.twa_test-1/split_lib_slice_9_apk.apk"],nativeLibraryDirectories=[/data/app/com.example.tw
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at java.lang.Class dalvik.system.BaseDexClassLoader.findClass(java.lang.String) (BaseDexClassLoader.java:56)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String, boolean) (ClassLoader.java:380)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String) (ClassLoader.java:312)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.support.v4.view.ViewCompat.setBackground(android.view.View, android.graphics.drawable.Drawable) (ViewCompat.java:2341)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.support.v7.widget.ActionBarContainer.<init>(android.content.Context, android.util.AttributeSet) (ActionBarContainer.java:62)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at java.lang.Object java.lang.reflect.Constructor.newInstance0!(java.lang.Object[]) (Constructor.java:-2)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at java.lang.Object java.lang.reflect.Constructor.newInstance(java.lang.Object[]) (Constructor.java:430)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at android.view.View android.view.LayoutInflater.createView(java.lang.String, java.lang.String, android.util.AttributeSet) (LayoutInflater.java:645)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at android.view.View android.view.LayoutInflater.createViewFromTag(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet, boolean) (LayoutInflater.java:787)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at android.view.View android.view.LayoutInflater.createViewFromTag(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet) (LayoutInflater.java:727)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.view.LayoutInflater.rInflate(org.xmlpull.v1.XmlPullParser, android.view.View, android.content.Context, android.util.AttributeSet, boolean) (LayoutInflater.java:858)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.view.LayoutInflater.rInflateChildren(org.xmlpull.v1.XmlPullParser, android.view.View, android.util.AttributeSet, boolean) (LayoutInflater.java:821)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at android.view.View android.view.LayoutInflater.inflate(org.xmlpull.v1.XmlPullParser, android.view.ViewGroup, boolean) (LayoutInflater.java:518)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at android.view.View android.view.LayoutInflater.inflate(int, android.view.ViewGroup, boolean) (LayoutInflater.java:426)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at android.view.View android.view.LayoutInflater.inflate(int, android.view.ViewGroup) (LayoutInflater.java:377)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at android.view.ViewGroup android.support.v7.app.AppCompatDelegateImpl.createSubDecor() (AppCompatDelegateImpl.java:607)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.support.v7.app.AppCompatDelegateImpl.ensureSubDecor() (AppCompatDelegateImpl.java:518)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.support.v7.app.AppCompatDelegateImpl.onPostCreate(android.os.Bundle) (AppCompatDelegateImpl.java:299)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.support.v7.app.AppCompatActivity.onPostCreate(android.os.Bundle) (AppCompatActivity.java:98)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.app.Instrumentation.callActivityOnPostCreate(android.app.Activity, android.os.Bundle) (Instrumentation.java:1200)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at android.app.Activity android.app.ActivityThread.performLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent) (ActivityThread.java:2666)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.app.ActivityThread.handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:2751)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.app.ActivityThread.-wrap12(android.app.ActivityThread, android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:-1)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.app.ActivityThread$H.handleMessage(android.os.Message) (ActivityThread.java:1496)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:102)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.os.Looper.loop() (Looper.java:154)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:6186)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at java.lang.Object java.lang.reflect.Method.invoke!(java.lang.Object, java.lang.Object[]) (Method.java:-2)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run() (ZygoteInit.java:889)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:779)
2019-02-08 18:19:03.284 10880-10880/com.example.twa_test D/LauncherActivity: Using URL from Manifest (https://slexom.gitlab.io/namya/).
2019-02-08 18:19:03.284 10880-10880/com.example.twa_test D/LauncherActivity: Launching Trusted Web Activity.
2019-02-08 18:19:03.470 10880-10923/com.example.twa_test I/Mali: Mali API Version : 401
2019-02-08 18:19:03.470 10880-10923/com.example.twa_test I/Mali: Mali REVISION: Linux-r4p0-00rel0 BUILD_DATE: 2014-11-10 20:23:11
2019-02-08 18:19:03.477 10880-10923/com.example.twa_test I/OpenGLRenderer: Initialized EGL, version 1.4
2019-02-08 18:19:03.477 10880-10923/com.example.twa_test D/OpenGLRenderer: Swap behavior 1
2019-02-08 18:19:03.598 10880-10880/com.example.twa_test W/art: Before Android 4.1, method int android.support.v7.widget.DropDownListView.lookForSelectablePosition(int, boolean) would have incorrectly overridden the package-private method in android.widget.ListView
截图
我今天遇到了同样的问题,这就是我学到的:
在尝试测试您的 android 应用程序之前,请在此处测试您的声明:
https://developers.google.com/digital-asset-links/tools/generator
填写域,包和指纹,然后点击"Test Statement"
如果你看到
"Success! Host [your web app] grants app deep linking to [android package].",那么您的 Web 应用程序配置正确,您的设备或应用程序有问题。
您很可能会看到
"Invalid input field(s)"
您可以在“网络”选项卡上打开 Chrome 控制台以查看服务器输出。可能你会看到类似的东西
"Invalid site (URL cannot contain a path component, login information, query parameters or fragment identifiers)"
要解决此问题,您应该将 assetlinks.json 文件放入网络应用程序的 根目录 、
https://slexom.gitlab.io/.well-known/assetlinks.json
在你的情况下。
你可以查看我的示例 repository. As you could see my file is accessible from https://antipovandrey.github.io/PWA/.well-known/assetlinks.json
您可能已选择让 Google Play 使用他们生成的密钥对您的发行版进行签名,并且仅使用您的密钥进行上传。
如果这样做,请转至 Google Play 控制台 版本管理 -> 应用签名 并复制 应用签名证书 SHA-256 指纹并将其放入 assetlinks.json
文件中。
就我而言,我 运行 应用程序的风格与我用于签名的风格不符。只有我的应用程序的发布版本是使用 SHA 密钥登录的,我是 运行 调试版本中的应用程序。
运行 和我修正味道时预期的一样。
对于那些仍然面临这个问题的人,很可能在 assetlinks.json 中你使用的是来自 "Upload certificate" 而不是来自 "App signing certificate" 的 SHA256。您可以在 Google Play Console -> Release management -> App signing 中找到这两个证书。
同样的故事,assetlinks.json 验证成功,但 url 栏存在,建议来自 google 播放控制台的 SHA-256 不工作
当使用 google SHA-256 或只是更改指纹代码时,请务必清除 chrome 关于您以前的应用程序的缓存或检查 .json[=10= 的缓存控制]
经过一个星期的努力,终于成功了,这是我的两分钱:
如果您选择让 Google 为您管理您的密钥,则有两个密钥,
App Signing Key
和 Upload key
.
执行通用步骤后(设置 -> 应用程序完整性 -> 创建 Digital Asset Links JSON
)
[
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "PACKAGE.NAME.HERE",
"sha256_cert_fingerprints":["APP:SIGNING:CERTIFICATE:SHA_256:FINGERPRINT"]
}
}
]
并在以下位置公开:
https://your.domain/.well-known/assetlinks.json
(访问 url 验证 json 必须是一个 LIST/ARRAY 而不仅仅是 JSON 对象本身,否则验证将失败)
请注意,新构建的包是使用 Upload Key
而不是 App Signing Key
签名的,因此如果您尝试直接测试本地构建的 .apk 和 URL 栏将可见。
要真正测试链接是否有效,您必须从商店下载该应用程序(Production/Internal Test/Open 测试等),因为该应用程序由 google 签名App Signing certificate sha_256
版本成功推出商店后。
仅供参考:几个小时后我就遇到了这个问题,我想出了这个问题,问题是当我从生成时使用的实际包名生成 assetlinks.json
文件时使用了不同的包名android-project 通过 bubblewrap init
命令。
很高兴看到 url 栏现在被隐藏了,这太棒了!
我已按照 this 指南学习如何使用受信任的 Web Activity。一切正常,但地址栏仍然出现。一开始我认为这是因为当应用程序正在寻找 assetlinks.json 时,响应是 404。修复它但没有成功删除地址栏。我错过了什么吗?
Chrome版本:72.0.3626.96
Android 版本: 7.1.2 (LineageOS 14.1)
assetlinks.json
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target" : { "namespace": "android_app", "package_name": "com.example.twa_test",
"sha256_cert_fingerprints": ["2A:32:7D:B7:4D:0B:A5:6A:72:47:86:A3:2F:A6:BB:D8:26:DE:AB:7E:8B:EA:C7:16:80:EA:C3:F1:50:E7:8E:D1"] }
}]
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.twa_test">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<meta-data
android:name="asset_statements"
android:resource="@string/asset_statements" />
<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="https://slexom.gitlab.io/namya/" />
<!-- 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="slexom.gitlab.io/namya/" />
</intent-filter>
</activity>
</application>
</manifest>
res/values/strings.xml
<resources>
<string name="app_name">Namya</string>
<string name="asset_statements">
[{
\"relation\": [\"delegate_permission/common.handle_all_urls\"],
\"target\": {
\"namespace\": \"web\",
\"site\": \"https://slexom.gitlab.io/namya/\"}
}]
</string>
</resources>
build.gradle(项目)
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.3.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
maven { url "https://jitpack.io" }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
build.gradle(模块:app)
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.example.twa_test"
minSdkVersion 16
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.github.GoogleChrome.custom-tabs-client:customtabs:3a71a75c9f'
}
Logcat
2019-02-08 18:19:01.918 10880-10880/? I/art: Late-enabling -Xcheck:jni
2019-02-08 18:19:02.352 10880-10880/com.example.twa_test W/System:
ClassLoader referenced unknown path: /data/app/com.example.twa_test-1/lib/arm
2019-02-08 18:19:02.403 10880-10880/com.example.twa_test I/InstantRun:
starting instant run server: is main process
2019-02-08 18:19:02.478 10880-10896/com.example.twa_test D/libEGL: loaded /system/lib/egl/libEGL_mali.so
2019-02-08 18:19:02.510 10880-10896/com.example.twa_test D/libEGL: loaded /system/lib/egl/libGLESv1_CM_mali.so
2019-02-08 18:19:02.660 10880-10880/com.example.twa_test W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
2019-02-08 18:19:02.727 10880-10896/com.example.twa_test D/libEGL: loaded /system/lib/egl/libGLESv2_mali.so
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: Rejecting re-init on previously-failed class java.lang.Class<android.support.v4.view.ViewCompat$OnUnhandledKeyEventListenerWrapper>: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/view/View$OnUnhandledKeyEventListener;
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.support.v4.view.ViewCompat.setBackground(android.view.View, android.graphics.drawable.Drawable) (ViewCompat.java:2341)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.support.v7.widget.ActionBarContainer.<init>(android.content.Context, android.util.AttributeSet) (ActionBarContainer.java:62)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at java.lang.Object java.lang.reflect.Constructor.newInstance0!(java.lang.Object[]) (Constructor.java:-2)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at java.lang.Object java.lang.reflect.Constructor.newInstance(java.lang.Object[]) (Constructor.java:430)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at android.view.View android.view.LayoutInflater.createView(java.lang.String, java.lang.String, android.util.AttributeSet) (LayoutInflater.java:645)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at android.view.View android.view.LayoutInflater.createViewFromTag(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet, boolean) (LayoutInflater.java:787)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at android.view.View android.view.LayoutInflater.createViewFromTag(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet) (LayoutInflater.java:727)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.view.LayoutInflater.rInflate(org.xmlpull.v1.XmlPullParser, android.view.View, android.content.Context, android.util.AttributeSet, boolean) (LayoutInflater.java:858)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.view.LayoutInflater.rInflateChildren(org.xmlpull.v1.XmlPullParser, android.view.View, android.util.AttributeSet, boolean) (LayoutInflater.java:821)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at android.view.View android.view.LayoutInflater.inflate(org.xmlpull.v1.XmlPullParser, android.view.ViewGroup, boolean) (LayoutInflater.java:518)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at android.view.View android.view.LayoutInflater.inflate(int, android.view.ViewGroup, boolean) (LayoutInflater.java:426)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at android.view.View android.view.LayoutInflater.inflate(int, android.view.ViewGroup) (LayoutInflater.java:377)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at android.view.ViewGroup android.support.v7.app.AppCompatDelegateImpl.createSubDecor() (AppCompatDelegateImpl.java:607)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.support.v7.app.AppCompatDelegateImpl.ensureSubDecor() (AppCompatDelegateImpl.java:518)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.support.v7.app.AppCompatDelegateImpl.onPostCreate(android.os.Bundle) (AppCompatDelegateImpl.java:299)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.support.v7.app.AppCompatActivity.onPostCreate(android.os.Bundle) (AppCompatActivity.java:98)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.app.Instrumentation.callActivityOnPostCreate(android.app.Activity, android.os.Bundle) (Instrumentation.java:1200)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at android.app.Activity android.app.ActivityThread.performLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent) (ActivityThread.java:2666)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.app.ActivityThread.handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:2751)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.app.ActivityThread.-wrap12(android.app.ActivityThread, android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:-1)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.app.ActivityThread$H.handleMessage(android.os.Message) (ActivityThread.java:1496)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:102)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.os.Looper.loop() (Looper.java:154)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:6186)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at java.lang.Object java.lang.reflect.Method.invoke!(java.lang.Object, java.lang.Object[]) (Method.java:-2)
2019-02-08 18:19:02.920 10880-10880/com.example.twa_test I/art: at void com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run() (ZygoteInit.java:889)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:779)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: Caused by: java.lang.ClassNotFoundException: Didn't find class "android.view.View$OnUnhandledKeyEventListener" on path: DexPathList[[zip file "/data/app/com.example.twa_test-1/base.apk", zip file "/data/app/com.example.twa_test-1/split_lib_dependencies_apk.apk", zip file "/data/app/com.example.twa_test-1/split_lib_slice_0_apk.apk", zip file "/data/app/com.example.twa_test-1/split_lib_slice_1_apk.apk", zip file "/data/app/com.example.twa_test-1/split_lib_slice_2_apk.apk", zip file "/data/app/com.example.twa_test-1/split_lib_slice_3_apk.apk", zip file "/data/app/com.example.twa_test-1/split_lib_slice_4_apk.apk", zip file "/data/app/com.example.twa_test-1/split_lib_slice_5_apk.apk", zip file "/data/app/com.example.twa_test-1/split_lib_slice_6_apk.apk", zip file "/data/app/com.example.twa_test-1/split_lib_slice_7_apk.apk", zip file "/data/app/com.example.twa_test-1/split_lib_slice_8_apk.apk", zip file "/data/app/com.example.twa_test-1/split_lib_slice_9_apk.apk"],nativeLibraryDirectories=[/data/app/com.example.tw
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at java.lang.Class dalvik.system.BaseDexClassLoader.findClass(java.lang.String) (BaseDexClassLoader.java:56)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String, boolean) (ClassLoader.java:380)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String) (ClassLoader.java:312)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.support.v4.view.ViewCompat.setBackground(android.view.View, android.graphics.drawable.Drawable) (ViewCompat.java:2341)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.support.v7.widget.ActionBarContainer.<init>(android.content.Context, android.util.AttributeSet) (ActionBarContainer.java:62)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at java.lang.Object java.lang.reflect.Constructor.newInstance0!(java.lang.Object[]) (Constructor.java:-2)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at java.lang.Object java.lang.reflect.Constructor.newInstance(java.lang.Object[]) (Constructor.java:430)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at android.view.View android.view.LayoutInflater.createView(java.lang.String, java.lang.String, android.util.AttributeSet) (LayoutInflater.java:645)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at android.view.View android.view.LayoutInflater.createViewFromTag(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet, boolean) (LayoutInflater.java:787)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at android.view.View android.view.LayoutInflater.createViewFromTag(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet) (LayoutInflater.java:727)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.view.LayoutInflater.rInflate(org.xmlpull.v1.XmlPullParser, android.view.View, android.content.Context, android.util.AttributeSet, boolean) (LayoutInflater.java:858)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.view.LayoutInflater.rInflateChildren(org.xmlpull.v1.XmlPullParser, android.view.View, android.util.AttributeSet, boolean) (LayoutInflater.java:821)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at android.view.View android.view.LayoutInflater.inflate(org.xmlpull.v1.XmlPullParser, android.view.ViewGroup, boolean) (LayoutInflater.java:518)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at android.view.View android.view.LayoutInflater.inflate(int, android.view.ViewGroup, boolean) (LayoutInflater.java:426)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at android.view.View android.view.LayoutInflater.inflate(int, android.view.ViewGroup) (LayoutInflater.java:377)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at android.view.ViewGroup android.support.v7.app.AppCompatDelegateImpl.createSubDecor() (AppCompatDelegateImpl.java:607)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.support.v7.app.AppCompatDelegateImpl.ensureSubDecor() (AppCompatDelegateImpl.java:518)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.support.v7.app.AppCompatDelegateImpl.onPostCreate(android.os.Bundle) (AppCompatDelegateImpl.java:299)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.support.v7.app.AppCompatActivity.onPostCreate(android.os.Bundle) (AppCompatActivity.java:98)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.app.Instrumentation.callActivityOnPostCreate(android.app.Activity, android.os.Bundle) (Instrumentation.java:1200)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at android.app.Activity android.app.ActivityThread.performLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent) (ActivityThread.java:2666)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.app.ActivityThread.handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:2751)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.app.ActivityThread.-wrap12(android.app.ActivityThread, android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:-1)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.app.ActivityThread$H.handleMessage(android.os.Message) (ActivityThread.java:1496)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:102)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.os.Looper.loop() (Looper.java:154)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:6186)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at java.lang.Object java.lang.reflect.Method.invoke!(java.lang.Object, java.lang.Object[]) (Method.java:-2)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run() (ZygoteInit.java:889)
2019-02-08 18:19:02.921 10880-10880/com.example.twa_test I/art: at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:779)
2019-02-08 18:19:03.284 10880-10880/com.example.twa_test D/LauncherActivity: Using URL from Manifest (https://slexom.gitlab.io/namya/).
2019-02-08 18:19:03.284 10880-10880/com.example.twa_test D/LauncherActivity: Launching Trusted Web Activity.
2019-02-08 18:19:03.470 10880-10923/com.example.twa_test I/Mali: Mali API Version : 401
2019-02-08 18:19:03.470 10880-10923/com.example.twa_test I/Mali: Mali REVISION: Linux-r4p0-00rel0 BUILD_DATE: 2014-11-10 20:23:11
2019-02-08 18:19:03.477 10880-10923/com.example.twa_test I/OpenGLRenderer: Initialized EGL, version 1.4
2019-02-08 18:19:03.477 10880-10923/com.example.twa_test D/OpenGLRenderer: Swap behavior 1
2019-02-08 18:19:03.598 10880-10880/com.example.twa_test W/art: Before Android 4.1, method int android.support.v7.widget.DropDownListView.lookForSelectablePosition(int, boolean) would have incorrectly overridden the package-private method in android.widget.ListView
截图
我今天遇到了同样的问题,这就是我学到的:
在尝试测试您的 android 应用程序之前,请在此处测试您的声明:
https://developers.google.com/digital-asset-links/tools/generator
填写域,包和指纹,然后点击"Test Statement"
如果你看到
"Success! Host [your web app] grants app deep linking to [android package].",那么您的 Web 应用程序配置正确,您的设备或应用程序有问题。
您很可能会看到
"Invalid input field(s)"
您可以在“网络”选项卡上打开 Chrome 控制台以查看服务器输出。可能你会看到类似的东西
"Invalid site (URL cannot contain a path component, login information, query parameters or fragment identifiers)"
要解决此问题,您应该将 assetlinks.json 文件放入网络应用程序的 根目录 、
https://slexom.gitlab.io/.well-known/assetlinks.json
在你的情况下。
你可以查看我的示例 repository. As you could see my file is accessible from https://antipovandrey.github.io/PWA/.well-known/assetlinks.json
您可能已选择让 Google Play 使用他们生成的密钥对您的发行版进行签名,并且仅使用您的密钥进行上传。
如果这样做,请转至 Google Play 控制台 版本管理 -> 应用签名 并复制 应用签名证书 SHA-256 指纹并将其放入 assetlinks.json
文件中。
就我而言,我 运行 应用程序的风格与我用于签名的风格不符。只有我的应用程序的发布版本是使用 SHA 密钥登录的,我是 运行 调试版本中的应用程序。
运行 和我修正味道时预期的一样。
对于那些仍然面临这个问题的人,很可能在 assetlinks.json 中你使用的是来自 "Upload certificate" 而不是来自 "App signing certificate" 的 SHA256。您可以在 Google Play Console -> Release management -> App signing 中找到这两个证书。
同样的故事,assetlinks.json 验证成功,但 url 栏存在,建议来自 google 播放控制台的 SHA-256 不工作
当使用 google SHA-256 或只是更改指纹代码时,请务必清除 chrome 关于您以前的应用程序的缓存或检查 .json[=10= 的缓存控制]
经过一个星期的努力,终于成功了,这是我的两分钱:
如果您选择让 Google 为您管理您的密钥,则有两个密钥,
App Signing Key
和 Upload key
.
执行通用步骤后(设置 -> 应用程序完整性 -> 创建 Digital Asset Links JSON
)
[
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "PACKAGE.NAME.HERE",
"sha256_cert_fingerprints":["APP:SIGNING:CERTIFICATE:SHA_256:FINGERPRINT"]
}
}
]
并在以下位置公开:
https://your.domain/.well-known/assetlinks.json
(访问 url 验证 json 必须是一个 LIST/ARRAY 而不仅仅是 JSON 对象本身,否则验证将失败)
请注意,新构建的包是使用 Upload Key
而不是 App Signing Key
签名的,因此如果您尝试直接测试本地构建的 .apk 和 URL 栏将可见。
要真正测试链接是否有效,您必须从商店下载该应用程序(Production/Internal Test/Open 测试等),因为该应用程序由 google 签名App Signing certificate sha_256
版本成功推出商店后。
仅供参考:几个小时后我就遇到了这个问题,我想出了这个问题,问题是当我从生成时使用的实际包名生成 assetlinks.json
文件时使用了不同的包名android-project 通过 bubblewrap init
命令。
很高兴看到 url 栏现在被隐藏了,这太棒了!