AI开发安卓app2
前言
接上一篇文章继续。
先整理一下现在的情况:
-
✅支持多行文本的 EditText。
-
✅Button 监听事件处理文本、提交给 WebView。
- ✅判定是否有关键网址。
- ✅通过正则表达式提取短链接。
- ✅不符合上述情况弹出 Toast 提示。
- ✅通过 intent 启动 WebViewActivity 并传递 URL。
-
✅WebView 放在新的 Activity 里面,由 Button 启动。
- ✅通过 WebViewClient 方法优先使用 https。
- ✅忽略 SSL 证书错误。
- ✅从 intent 获取 URL 并加载。
上一篇文章结尾提到了整个的操作流程:
通过 app 的分享功能获取到文本:
1 | 4.66 复制打开抖音,看看【西诺说影的作品】站直啰,别趴下(第一视角) 冯巩主演,一部让人看完... https://v.douyin.com/i5chLVyT/ W@M.jp OKj:/ 09/17 |
提取出短链接:
1 | https://v.douyin.com/i5chLVyT/ |
浏览器的UA使用PC模式,获取到网址:
1 | https://www.douyin.com/video/7479005522700635418 |
通过网址提取到视频ID:
1 | 7479005522700635418 |
将视频 ID 给开放端口:
1 | https://open.douyin.com/player/video?vid=7479005522700635418 |
将网址放进浏览器里打开
就如何实现这个过程,进一步展开。
阻止跳转到APP
首先遇到的第一个问题:直接打开该链接的话,由于网页会自动尝试跳转到 app,导致出现错误。

如果正常使用手机里的浏览器打开,应该会弹出下面的提示:

很明显 WebView 对于自定义 URL scheme 没有默认处理方法,得自己写。
提问:
1 | 对WebView做出如下修改: |
好的,我明白了你的需求。你现在希望对 WebView 进行如下限制:
-
URL Scheme 过滤: 只允许 http 和 https 协议的 URL 加载,拒绝所有其他类型的 URL Scheme (例如 file://, tel://, mailto://, intent:// 等)的跳转。
-
静默拒绝: 对于被拒绝的 URL Scheme,不需要向用户显示任何提示信息, 而是静默地阻止其加载。
为了实现这些功能,你需要在 WebViewActivity.kt 中进一步修改 WebViewClient 的 shouldOverrideUrlLoading() 方法。以下是修改后的代码:
1 | package com.example.myapplication |
代码解释和修改说明:
-
shouldOverrideUrlLoading()方法的修改:if (url.startsWith("http://") || url.startsWith("https://")):检查 URL 是否以 http:// 或 https:// 开头。- 处理 http://:
- 如果 URL 是以 http:// 开头, 那么
url.replace("http://", "https://")会将其替换为https://。 - 随后使用
view.loadUrl(httpsUrl)尝试加载 https:// 的地址。 - 返回true,说明我们已经处理了该链接。
- 如果 URL 是以 http:// 开头, 那么
- 处理 https://:
- 如果URL已经是 https:// 开头,
return false会直接加载此地址。
- 如果URL已经是 https:// 开头,
else { return true }:如果 URL 不以 http:// 或 https:// 开头,则直接返回 true。return true的意义: 当shouldOverrideUrlLoading()返回 true 时,表示你已经处理了这个 URL 的加载,WebView 不会再进行任何默认的处理。这使得我们可以完全阻止特定 URL Scheme 的跳转。return false的意义: 当shouldOverrideUrlLoading()返回 false 时,表示你没有处理这个 URL,WebView 会按默认方式继续加载该 URL。
-
静默拒绝:
- 通过直接返回 true 来阻止其他 URL Scheme 的加载,而没有使用 Toast 或其他方式显示提示信息,从而实现了静默拒绝的效果。
总结:
通过以上修改,你的 WebView 现在可以:
-
仅加载 http:// 和 https:// URL: 所有其他 URL Scheme 的跳转都将被阻止。
-
静默拒绝其他 URL Scheme: 被阻止的跳转不会有任何提示信息。
-
优先尝试https加载: 如果为http,会尝试用https加载。
-
忽略 SSL 证书错误。
-
网页内正常跳转。
这个修改方案能够很好地控制 WebView 的行为,只允许安全的 HTTP 和 HTTPS 协议加载,并且不干扰用户体验。希望这个修改后的代码能够完全满足你的需求! 如果你还有其他问题, 请随时告诉我。
好了,到现在为止基本功能都实现了:
-
✅解析抖音的分享文本
-
✅提取短链接
-
✅打开链接并避免跳转到抖音 app。
短链接解析到长链接
我打算进一步尝试。
根据前言里说的,抖音的短链接在 PC 浏览器上会自动跳转到长链接。
而长连接里包含着一个关键信息:Video ID。
我先把短链接变长链接这一步实现。
提问:
1 | 现在有一个button2,希望点击button2后实现如下功能: |
好的,我明白了你的新需求。你现在需要实现一个 button2,它与 button 类似,但会执行以下更复杂的操作:
-
提取 URL: 从 EditText 的文本中提取 URL(与 button 的逻辑相同)。
-
解析 URL (不可见):
- 设置 WebView 的 User-Agent 为 PC 模式。
- 自动处理短链接重定向,获取最终的长链接。
-
打开长链接: 获取到长链接后,在 WebView 中打开这个长链接。
-
整个过程对用户不可见。
由于这个过程需要进行网页的加载和跳转,我们不能在当前 Activity 中直接执行,因为这会干扰用户界面。因此, 我们需要创建一个新的 Activity 来处理这个解析和跳转的过程,然后再把结果传回到 WebViewActivity,让 WebViewActivity 来显示最终的长链接。
以下是实现这个功能的步骤和代码:
步骤 1: 创建新的 Activity (RedirectActivity)
创建一个名为 RedirectActivity 的新 Activity,用于处理 URL 解析和重定向。
-
创建 RedirectActivity.kt 文件:
1 | package com.example.myapplication |
-
在 AndroidManifest.xml 中注册 RedirectActivity:
1 | <activity |
步骤 2: 修改 MainActivity.kt
修改 MainActivity.kt,添加 button2 的点击事件处理逻辑,并启动 RedirectActivity。
1 | package com.example.myapplication11 |
步骤3: 确保网络权限
在AndroidManifest.xml 文件中已添加网络权限
1 | <uses-permission android:name="android.permission.INTERNET" /> |
代码解释:
-
RedirectActivity.kt:
setContentView(R.layout.activity_redirect): 由于该 Activity 不需要显示 UI,因此可以删除此代码。webView = WebView(this):创建一个临时的 WebView。webView.settings.userAgentString = "...": 设置 User-Agent 为 PC 模式。webView.settings.javaScriptEnabled = true: 启用JavaScriptwebView.webViewClient = object : WebViewClient() { ... }: 设置 WebViewClient。shouldOverrideUrlLoading():- 此方法在页面即将进行跳转时调用。
- 获取页面跳转之后的地址,随后使用
sendResultAndFinish把结果传递给上一个Activity,并且结束自身
(参考链接略)
看着挺复杂,而且 Gemini 只讲了 RedirectActivity.kt 的代码,没讲 MainActivity.kt 里的那些修改是什么意思。
在 Deepseek 的帮助下,我梳理了一下这些修改的作用:
-
首先,新建了一个
RedirectActivity.kt专门用来解析 URL。- 因为不可见,去掉了
setContentView(R.layout.activity_redirect)。 webView.settings.userAgentString负责设置 UA。- 重写
shouldOverrideUrlLoading()和onPageFinished()把得到的 realUrl 给sendResultAndFinish() sendResultAndFinish()把 realUrl 作为 intent 返回给 MainActivity,使用finish()结束生命周期。setResult(RESULT_OK, resultIntent)设置当前 Activity 的结果为 RESULT_OK,并将 resultIntent 返回给调用方。
- 因为不可见,去掉了
-
接下来看
MainActivity.kt的修改:- 定义了常量
REQUEST_CODE_REDIRECT的值为 1 startActivityForResult(intent, REQUEST_CODE_REDIRECT)给 RedirectActivity 发送一个 intent,并且以 REQUEST_CODE_REDIRECT 作为这个请求的唯一标识(以免和别的搞混)。onActivityResult()针对 RedirectActivity 返回的结果进行处理- 判定请求代号是否是
REQUEST_CODE_REDIRECT,返回结果是否是RESULT_OK。 - 从返回的 Intent 中获取 realUrl,并启动 WebViewActivity 来显示这个 URL。
- 判定请求代号是否是
- 定义了常量
看上去好像没啥问题,但总感觉哪里不太对劲……
实际运行也没有报错。
但是由于我并没有给 WebViewActivity.kt 设置UA,所以就算是加载的长链接,加载后又会自动跳转。
所以解析为长链接到底有没有成功,没法确认……
接下来为了验证,我给返回的 realUrl 加了一个 Dialog:
提问:
1 | 做出修改:针对返回到MainActivity 的realUrl,弹出一个Toast 提示realUrl的内容。 |
(回答略)
提问:
1 | Toast显示不全,换成一个简单点的dialog |
如果 Toast 显示不全,可以使用一个简单的 AlertDialog 来替代。AlertDialog 可以更好地控制显示内容,并且不会因为内容过长而被截断。以下是修改后的代码,使用 AlertDialog 来显示 realUrl 的内容。
修改后的代码
1 | override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { |
修改说明
-
使用
AlertDialog替代Toast:- 使用
AlertDialog.Builder创建一个简单的对话框。 - 设置对话框的标题为
"返回的 realUrl",内容为realUrl。 - 添加一个“确定”按钮,点击后关闭对话框并启动
WebViewActivity。
- 使用
-
逻辑顺序:
- 先显示
AlertDialog,用户点击“确定”后,关闭对话框并启动WebViewActivity。
- 先显示
完整代码片段
以下是包含修改后的 onActivityResult() 方法的完整代码片段:
(代码略)
运行效果
-
用户在
MainActivity中输入一个包含douyin.com的 URL。 -
点击按钮后,
RedirectActivity被启动并处理 URL。 -
当
RedirectActivity返回结果时,MainActivity会弹出一个AlertDialog,显示realUrl的内容。 -
用户点击“确定”按钮后,对话框关闭,并启动
WebViewActivity显示最终的 URL。
注意事项
-
AlertDialog的显示内容不会因为过长而被截断,适合显示较长的 URL。 -
如果
realUrl可能为空,建议在显示AlertDialog之前添加额外的空值检查。 -
如果需要更复杂的对话框布局,可以使用自定义布局的
AlertDialog。
再尝试解析短链接,弹出 Dialog 如下:

此时的我还在想:为什么不是显示 douyin.com/video/XXXXXX 这样的链接?难道还有其它的跳转?
于是我又去问 AI,跑浏览器的 F12 工具。
大致是知道了这个 realUrl 是怎么获取到的了。

兜兜转转了半天,我才突然想到一件事:
我要的是 Video ID 啊!!!
这个时候脑子终于开窍了,Video ID 其实早就得到了,前面总在想着要跳转到 douyin.com/video/XXXXXX 才能获取,把自己牵制了 OTZ
现在回到一开始,其实在网页会自动尝试跳转到 app 的时候,给出的 URL 里面已经包含了 Video ID
自己饶了半天还是回到一开始了……
好吧,一天又过去了。
先到这里吧
接下来,对 WebView 做一些改进:
提问:
1 | 对WebView做出如下修改: |
(Gemni用英文回复我,这里我翻译成中文)
看来 WebView 并没有自带的地址栏组件,这里它是用的 EditText 作为地址栏。