[Android] 外部链接唤醒App

本文详细介绍了如何通过外部链接启动Android应用的方法,并针对常见的首页Activity无法重新启动的问题提供了具体的解决方案。涉及的技术要点包括Intent过滤器的配置、Activity的启动模式以及如何使用FLAG_ACTIVITY_NEW_TASK标志实现跨任务的启动。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

移动互联网发展到今天,一个移动app需要和各种各样的外部链接关联,它不再仅仅从手机的桌面启动,更多的将会从其他的应用、浏览器链接、短信、二维码或者微信分享等渠道启动,这里涉及到的是各种各样的营销渠道和方式。

那么从我们的技术角度来说,我们今天要说明一下的是,从外部链接的方式启动app需要注意的地方。我们都是知道,在Android上外链方式启动app的方式是在manifest文件中的某个activity的intent-filter标签中设置好标签action、category和data的属性。

<intent-filter>
    <!--接收外部跳转-->
    <action android:name="android.intent.action.VIEW" />
    <!--表示该页面可以被隐式调用,必须加上该项-->
    <category android:name="android.intent.category.DEFAULT" />
    <!--如果希望该应用可以通过浏览器的连接启动,则添加该项-->
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="scheme"/>
</intent-filter>

浏览器页面代码加载协议为android:scheme属性值的链接向系统发起调用服务请求,系统的广播系统就会匹配当前系统中的intent-filter,如果其子标签的action、category和data都匹配的话,则会调起此activity,如果app没有加载,则先加载app的apk到进程,再启动对应的activity。

坑和经验

问题来了,很多app的首页activity都是在显示完SplashActivity后再启动的,首页activity的launchMode都是设置为singleTask,确保实例的唯一性,当我们的app已经启动了的情况下,再次通过外链的方式启动首页activity是无法启动的。

从android的task堆栈角度来说,浏览器activity所在task是在浏览器的process当中的,而起启动SplashActivity后此activity是在浏览器所在的task,此时在SplashActivity中启动app的首页activity,而首页activity是在另外的process的task当中,故无法切换这个task到前台。

此时的解决方案是在启动首页activity的intent对象中添加FLAG_ACTIVITY_NEW_TASK,在浏览器器task中通过FLAG_ACTIVITY_NEW_TASK启动首页activity,此时系统会寻找和首页activity具有相同的taskAffinity的task,即找到app的process中首页所在的task,将此task推到前台,到此实现了通过外链的方式再次现身app首页activity的功能。

总结一下,FLAG_ACTIVITY_NEW_TASK针对启动的activity是否在同一个process中处理方式不一样,因为默认情况下相同应用中所有的activity的taskAffinity都相同,故如果是存在且在同一应用中,直接将被启动的activity入栈,否则新建一个task并入栈,故在我们的开发中,对于activity间的切换以及task间的切换需要深入理解才能做出优秀的软件。






<think>我们参考用户提供的引用内容,特别是引用[1]和引用[3]中关于URL Scheme在UniApp中的使用。 用户需求:了解UniApp中如何通过Scheme唤醒App的指南。 步骤: 1. 配置URL Scheme:在manifest.json文件中配置iOS和Android的URL Scheme。 2. 处理外部唤醒:在App中编写代码,监听处理外部URL的唤醒事件。 3. 实现跳转逻辑:解析URL参数,跳转到指定页面。 详细步骤: 一、配置URL Scheme 在UniApp项目中,打开manifest.json文件,进行如下配置: 对于Android平台,在"app-plus" -> "distribute" -> "android"节点下配置scheme: 对于iOS平台,在"app-plus" -> "distribute" -> "ios"节点下配置scheme,同时需要在"urlschemewhitelist"(白名单)中添加需要使用的scheme(如微信的weixin、wechat等)。 示例配置(manifest.json): ```json { "app-plus": { "distribute": { "android": { "schemes": ["myapp"] // Android的URL Scheme }, "ios": { "schemes": ["myapp"], // iOS的URL Scheme "urlschemewhitelist": ["weixin", "wechat"] // 如果需要检测或唤醒微信,需要将微信的scheme加入白名单 } } } } ``` 二、处理外部唤醒App启动时,需要监听处理外部URL的唤醒事件。UniApp提供了`onLaunch`和`onShow`生命周期函数,我们可以在这里获取启动参数。 在App.vue中,我们可以通过`onShow`方法获取传递过来的参数。 示例代码(App.vue): ```javascript export default { onShow: function(options) { // 获取启动参数 const args = plus.runtime.arguments; if (args) { // 处理args,例如解析URL // 假设外部唤醒的URL为 myapp://detail?id=123 // 这里可以将参数传递给指定页面,然后跳转 console.log('唤醒参数:', args); // 解析URL,获取参数 // 这里简单示例,实际需要根据URL格式解析 let pagePath = ''; let query = {}; // 实际解析逻辑需要根据你的URL格式来写 // 例如:如果args是完整URL,可以使用URL对象解析(注意:在App端,可能不是标准的http/https,需要自己处理) // 这里简化处理,假设我们已经解析出要跳转的页面和参数 pagePath = '/pages/detail/detail'; query = { id: '123' }; // 从URL中解析出的参数 // 跳转到指定页面 uni.navigateTo({ url: pagePath + '?' + Object.keys(query).map(key => `${key}=${encodeURIComponent(query[key])}`).join('&') }); } } } ``` 注意:由于外部唤醒可能发生在App已经运行(在后台)的情况下,我们还需要考虑在App运行时被唤醒的情况。上述代码在`onShow`中处理,可以覆盖冷启动和热唤醒。 三、实现跳转逻辑 在第二步中,我们已经将参数传递给了目标页面。在目标页面(如detail页面)的onLoad生命周期中,可以获取传递的参数。 示例代码(detail.vue): ```javascript export default { onLoad(options) { // options 中包含了传递的参数 console.log('页面参数:', options); // 根据参数id获取详情内容 if (options.id) { this.loadDetail(options.id); } }, methods: { loadDetail(id) { // 根据id请求详情数据 } } } ``` 四、生成外部唤醒链接 外部唤醒的链接格式为:`[scheme]://[host]/[path]?[query]`,其中scheme就是我们在manifest.json中配置的scheme(如myapp),host、path和query可以根据需要定义。 例如:`myapp://detail?id=123`,表示唤醒App并跳转到详情页,参数id为123。 五、注意事项 1. iOS平台需要配置白名单(urlschemewhitelist),否则无法唤醒其他App(如微信)或无法被其他App唤醒。 2. 在Android平台上,如果App被杀死,通过URL Scheme唤醒时,启动参数可以在App.vue的`onLaunch`和`onShow`中获取。但在App后台运行时,唤醒会触发`onShow`,而不会触发`onLaunch`。 3. 在iOS平台上,如果App被杀死,通过URL Scheme唤醒时,启动参数在`onLaunch`和`onShow`中都可以获取,但通常推荐在`onShow`中处理,因为`onLaunch`在App启动时只触发一次,而`onShow`在每次App显示时都会触发(包括从后台唤醒)。 六、高级:通过Universal Link(通用链接)唤醒 除了URL Scheme,还可以使用Universal Link(iOS)和App Link(Android)来实现唤醒。这种方式使用标准的HTTPS链接,在用户未安装App时可以打开网页,安装App则直接打开App。但UniApp目前对Universal Link的支持需要额外配置,且相对复杂。具体可参考引用[2]中的内容。 由于用户问题主要关注Scheme,这里不展开Universal Link。 七、封装工具函数(参考引用[3]) 我们可以封装一个工具函数来检测并唤醒其他App(如微信),同时支持传递参数。 示例工具函数(appLauncher.js): ```javascript // utils/appLauncher.js export const launchApp = (params) => { // #ifdef APP-PLUS const { pname, iosScheme, data } = params; const isAndroid = plus.os.name.toLowerCase() === 'android'; const appInfo = { pname: isAndroid ? pname : undefined, // Android包名 action: !isAndroid ? iosScheme : undefined, // iOS的scheme extra: data || {} // 传递的参数 }; return new Promise((resolve, reject) => { // 检查应用是否安装 const exist = plus.runtime.isApplicationExist(appInfo); if (!exist) { reject('APP_NOT_INSTALLED'); return; } // 唤醒应用 plus.runtime.launchApplication(appInfo, (err) => { if (err) { reject('LAUNCH_FAILED'); } else { resolve('SUCCESS'); } }); }); // #endif }; ``` 使用示例: ```javascript import { launchApp } from '@/utils/appLauncher.js'; // 唤醒微信 launchApp({ pname: 'com.tencent.mm', // 微信的Android包名 iosScheme: 'weixin://', // 微信的iOS Scheme data: {} // 可以传递参数,但微信是否接收参数取决于微信的URL Scheme接口 }).then(() => { console.log('唤醒成功'); }).catch(err => { console.log(err); // 如果微信未安装,可以提示用户 uni.showToast({ title: '未安装微信', icon: 'none' }); }); ``` 注意:唤醒其他App需要知道目标App的URL Scheme(iOS)或包名(Android),并且目标App必须支持通过URL Scheme唤醒。 以上就是在UniApp中通过Scheme唤醒App的指南。 根据要求,生成相关问题: 1. 如何在UniApp中配置Universal Link实现唤醒? 2. UniApp中如何区分冷启动和热唤醒? 3. 如何解析URL Scheme中的复杂参数?</think>### UniApp 通过 Scheme 唤醒 App 指南 在 UniApp 中通过 URL Scheme 唤醒 App 主要涉及以下核心步骤,支持 iOS 和 Android 平台: #### 一、配置 URL Scheme 1. **Android 配置** 在 `manifest.json` 中添加: ```json "app-plus": { "distribute": { "android": { "schemes": ["myapp"] // 自定义 Scheme 名称 } } } ``` 2. **iOS 配置** 在 `manifest.json` 中添加 Scheme 和白名单: ```json "app-plus": { "distribute": { "ios": { "schemes": ["myapp"], // 自定义 Scheme "urlschemewhitelist": ["weixin", "wechat"] // 需检测的第三方 App 白名单 } } } ``` #### 二、处理外部唤醒事件 在 `App.vue` 中监听唤醒事件: ```javascript onShow: function(options) { // 获取唤醒参数(Android/iOS 通用) const args = plus.runtime.arguments; if (args) { // 示例:myapp://detail?id=123 → 解析跳转到详情页 const params = new URLSearchParams(args.split('?')[1]); const id = params.get('id'); uni.navigateTo({ url: `/pages/detail?id=${id}` }); } } ``` #### 三、生成唤醒链接 - **格式**:`[scheme]://[path]?[params]` 示例:`myapp://product/detail?id=1001` - **使用场景**: - 网页链接:`<a href="myapp://home">打开App</a>` - 二维码:嵌入 Scheme 链接 - 短信/邮件:`点击链接打开:myapp://login?token=xxx` #### 四、检测并唤醒第三方 App 封装工具函数(如 `appLauncher.js`): ```javascript export const launchApp = (params) => { const { pname, iosScheme, data } = params; const isAndroid = plus.os.name.toLowerCase() === 'android'; const appInfo = { pname: isAndroid ? pname : undefined, // Android 包名 action: !isAndroid ? iosScheme : undefined, // iOS Scheme extra: data || {} // 传递参数 }; return new Promise((resolve, reject) => { // 检测是否安装 if (!plus.runtime.isApplicationExist(appInfo)) { return reject('APP_NOT_INSTALLED'); } // 唤醒应用 plus.runtime.launchApplication(appInfo, (err) => { err ? reject('LAUNCH_FAILED') : resolve('SUCCESS'); }); }); }; ``` #### 五、使用示例(唤醒微信) ```javascript import { launchApp } from '@/utils/appLauncher'; // 唤醒微信并传递参数 launchApp({ pname: "com.tencent.mm", // Android 包名 iosScheme: "weixin://", // iOS Scheme data: { type: "share" } // 自定义参数 }).catch(err => { uni.showToast({ title: "微信未安装", icon: "none" }); }); ``` #### 注意事项 1. **iOS 白名单限制** iOS 9+ 必须配置 `urlschemewhitelist`,否则无法检测第三方 App[^3]。 2. **参数传递** 复杂数据需 JSON 序列化:`data: { payload: encodeURIComponent(JSON.stringify(obj)) }`。 3. **Android 包名** 通过应用商店查询或 Apk 解压获取(如微信包名:`com.tencent.mm`)。 4. **Scheme 冲突** 避免使用常见 Scheme(如 `http`/`weixin`),防止与系统应用冲突。 > **实践建议**:测试时直接用设备浏览器访问 `myapp://home`,观察是否成功唤醒 App[^1]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值