Android 四种launchMode及疑问

之前对于四种模式的理解仅限于理论和一两个简单的测试(singleTop和singleTask)

今天脑袋抽风想都实际测一下,晕,测到 singleInstance杯具了

请对四种模式熟悉的朋友直接跳到文章底部,帮忙看下singleInstance的问题,谢谢

 

未标明launchMode的Activity都是默认启动模式

1,standard

每次都会新建一个Activity实例

 

2,singleTask

栈空间简易示意:A -- B -- C

 最后用startActivity(intent)从C跳到A后,由于栈空间已经存在A的实例,A上面的Activity B和C出栈(即onDestroy销毁),A置于栈顶

如果A中重写了onNewIntent(...)方法,会同时接到C跳A的intent数据

 

3,singTop

栈空间简易示意:A -- B -- C

最后用startActivity(intent)从C跳到A后,即使栈控件已经存在A的实例,Android系统也会重新创建一个A的实例并且置于栈顶,当然重写的onNewIntent(...)方法也不会接到intent数据, 变成:

 

4,singleInstance(代码跳转逻辑:A -- B -- C -- A -- B -- C .....)

1,起始Activity非singleInstance (实际跳转顺序:A -- B -- C -- A -- B -- C .....)

 

A,C位于同一栈中,taskId相同, B在另一个栈中,与他们taskId不同,此栈在B未被销毁前只能有B一个Activity(B在创建之后,onNewIntent(...)也可以接到其他Activity跳转的intent数据),整个过程中,B只创建了一次,A与C每次都创建一个实例

2,起始Activity为singleInstance(实际跳转顺序:A -- B -- C -- A -- C -- A -- C .....)

代码中第一种情况相同,但实际跳转顺序却不同,

第一次A -- B -- C 实际跳转完成之后,当从C回到A(A在创建之后,onNewIntent(...)也可以接到其他Activity跳转的intent数据)后,再从A跳B时,却跳到了C页面,依次循环,整个过程中,B只是在一开始创建时出现了一次,之后从A都是直接跳C,A当然是单实例的,但是C也只创建了一次,相当于是单实例

多次跳转按物理返回键时:

如果当前页面是A,则A销毁,出现C,接着C销毁,出现B,B销毁,应用程序结束

如果当前页面是C,则C销毁,出现B,接着B销毁,出现A,A销毁,应用程序结束

返回键的实际跳转情况属于正常,因为A的taskId, 与B,C不同,不在同一栈中

<think>嗯,用户之前已经询问过如何在微信中通过自己的UniApp程序打开文件,现在他们再次提问,想要更详细地了解如何具体实现注册文件类型处理能力,特别是通过系统级Intent和URL Scheme的机制。我需要确定用户的需求是什么。 用户可能已经按照之前的指导尝试过配置,但遇到了问题,或者他们需要更具体的步骤来确保正确实现。他们的真实需求可能是希望确保UniApp应用能够正确响应微信的文件分享,处理不同平台(Android和iOS)的配置,并正确解析文件路径。 我需要回顾之前的回答,看看是否有哪些部分需要进一步详细说明。之前的回答涵盖了Android和iOS的配置文件类型处理,UniApp接收文件的代码示例,以及常见问题。用户现在可能希望得到更具体的代码示例,或者更详细的步骤,尤其是在处理Intent和URL Scheme时。 同时,要注意用户可能对Android和iOS的配置流程不太熟悉,特别是处理MIME类型和UTI的部分。需要详细解释每个配置项的作用,并提供示例代码。此外,用户可能在实际操作中遇到路径解析的问题,比如如何处理不同平台传递的URI,如何转换content://为实际路径等。 另外,用户可能对测试流程有疑问,比如如何正确打包应用进行测试,为什么调试模式可能无法注册等问题。需要强调正式打包的重要性,并提供测试的具体步骤。 最后,需要确保回答结构清晰,分步骤说明,并提供代码示例和常见问题解决方法,帮助用户逐步实现功能,避免遗漏关键配置步骤。</think>以下是实现微信通过系统级Intent/URL Scheme机制触发UniApp打开文件的详细技术方案: --- ### 一、Android平台实现(基于Intent) #### 1. 配置AndroidManifest.xml 在HBuilderX工程中定位到 `manifest.json` -> **源码视图** 添加: ```json "android": { "xml": ` <manifest> <application> <activity android:name="io.dcloud.PandoraEntry" android:launchMode="singleTask"> <!-- 核心配置 --> <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> <!-- 示例:处理PDF --> <data android:scheme="file" android:mimeType="application/pdf" android:pathPattern=".*\\.pdf"/> <!-- 处理所有文件类型 --> <data android:scheme="content"/> <data android:scheme="file"/> <data android:host="*"/> </intent-filter> </activity> </application> </manifest>` } ``` #### 2. 文件类型匹配策略 | 参数 | 说明 | 示例 | |------|------|------| | `mimeType` | MIME类型匹配 | `text/plain`/`image/*` | | `pathPattern` | 正则表达式匹配路径 | `.*\\.(txt|log)` | | `scheme` | URI协议 | `content`(微信常用)/`file` | #### 3. 路径解析处理(关键代码) 在App.vue的`onLaunch`中: ```javascript // Android接收content://uri if(plus.os.name === 'Android') { const intent = plus.android.runtimeMainActivity().getIntent(); const uri = intent.getData(); if(uri) { const fileUri = plus.android.invoke(uri, "toString"); const realPath = await this.convertContentUri(fileUri); } } methods: { async convertContentUri(uri) { // 通过ContentResolver获取真实路径 const Context = plus.android.importClass("android.content.Context"); const FileUtil = plus.android.importClass("android.os.FileUtils"); const cursor = context.getContentResolver().query( uri, [plus.android.invoke("android.provider.OpenableColumns", "DISPLAY_NAME")], null, null, null ); cursor.moveToFirst(); const name = cursor.getString(0); const inputStream = context.getContentResolver().openInputStream(uri); const cachePath = `${plus.io.PUBLIC_DOCUMENTS}/${name}`; const file = new java.io.File(cachePath); FileUtil.copy(inputStream, new FileOutputStream(file)); return cachePath; } } ``` --- ### 二、iOS平台实现(基于URL Scheme) #### 1. 配置Info.plist 在 `manifest.json` -> **源码视图** 添加: ```json "ios": { "urltypes": [ { "urlidentifier": "com.yourcompany.yourapp", "urlschemes": ["yourapp"] } ], "plist": { "CFBundleDocumentTypes": [ { "CFBundleTypeName": "PDF Document", "CFBundleTypeRole": "Viewer", "LSHandlerRank": "Alternate", "LSItemContentTypes": ["com.adobe.pdf"] } ] } } ``` #### 2. 文件接收处理 ```javascript // App.vue中监听universalLink onLaunch(options) { // #ifdef APP-PLUS if(plus.os.name === 'iOS') { const payload = plus.runtime.arguments; if(payload.indexOf('file://') !== -1) { const filePath = this.iosParseFilePath(payload); uni.$emit('wxFile', { path: filePath }); } } // #endif } methods: { iosParseFilePath(url) { // 示例:处理URL Scheme参数 // 微信传递格式:yourapp://path/to/file.pdf const q = url.split('//')[1]; return decodeURIComponent(q); } } ``` --- ### 三、跨平台通用处理 #### 1. 统一事件监听 ```javascript // 在页面中监听全局事件 created() { uni.$on('wxFileOpen', this.handleFileOpen); }, methods: { handleFileOpen(e) { console.log('收到文件:', e.path); // 执行文件操作(上传/预览等) } } ``` #### 2. 文件权限处理 ```javascript // 检查存储权限 async checkPermission() { const status = await uni.getSystemSetting({ type: 'storage' }); if(!status.authEnabled) { uni.showModal({ title: '权限申请', content: '需要文件读取权限', success: (res) => { uni.requestSystemAuthorization({ type: 'storage' }); } }); } } ``` --- ### 四、微信侧限制规避方案 1. **Android 11+适配**: ```xml <!-- 添加在AndroidManifest.xml --> <queries> <intent> <action android:name="android.intent.action.VIEW" /> <data android:mimeType="*/*" /> </intent> </queries> ``` 2. **iOS沙盒文件处理**: ```javascript // 将接收的文件复制到应用沙盒 const tempPath = `${plus.io.PUBLIC_DOCUMENTS}/${Date.now()}.pdf`; await uni.downloadFile({ url: filePath, filePath: tempPath }); ``` --- ### 五、调试技巧 1. **Android Intent测试**: ```bash adb shell am start -a android.intent.action.VIEW -d "file:///sdcard/test.pdf" -t "application/pdf" ``` 2. **iOS URL Scheme测试**: ```bash xcrun simctl openurl booted yourapp://test.pdf ``` 3. **日志过滤**: ```bash adb logcat | grep 'ActivityTaskManager' ``` --- ### 六、典型问题解决方案 | 问题现象 | 排查步骤 | |---------|----------| | 应用未出现在分享列表 | 1. 检查mimeType是否与文件类型匹配<br>2. 确认APK已正式签名<br>3. Android 11+需添加`<queries>`声明 | | 收到路径但无法读取 | 1. Android检查`READ_EXTERNAL_STORAGE`权限<br>2. iOS检查沙盒目录访问权限<br>3. 验证URI转换逻辑 | | 多次触发文件接收 | 在Activity配置中添加`android:launchMode="singleTask"` | --- 以上方案需注意:微信Android客户端从v8.0.16版本开始对`content://` URI增加了访问限制,建议通过`uni.downloadFile`先将文件下载到应用私有目录再处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值