Android Launcher构建之模型(LauncherModel.java)实现

本文深入探讨了基于MVC模型构建的Launcher系统,详细解释了系统如何通过界面反应模型状态,并处理用户与系统事件。主要内容包括读取数据库设置、管理应用布局、响应系统广播以及用户界面交互等关键功能。

        基于MVC模型构建之Launcher系统,通过界面(VIEW)反应模型(MODEL)状态。同时所有需要被记录的用户与系统事件,最终都会交由模型来处理,以决定是改动到SQlite还是内部容器。在Launcher应用中模型需要完成的主要工作如下:

1.通过ContentProvider读取WorkSpace数据库排布设置

        WorkSpace用户排布需要存储到launcher.db,保证下次开机能回到先前的状态。通过ContentProvider将SQlite数据读写托管,模型端通过系统提供的ContentResolver解析读取到数据。launcher.db数据不存在则loadFavorites(db, R.xml.default_workspace)创建,存在则直接读取。
2.将workspace排布与APP信息写入状态容器。
         接下来就是将ContentResolver获取到的内容还原到XXXInfo(ShortcutInfo,LauncherAppWidgetInfo等),并根据ITEM_TYPE定义放入对应的影子容器中。但放入前必须使用checkItemPlacement 方法检验提取到的数据是否可以被放置,如无法放置将不出现在容器内。
3.利用状态容器内容构建用户界面。
       当图标位置信息加载完毕,接下来就是回调子类实现的interface Callbacks方法,UI线程开始添加对应的对象到界面。而launcher-loader线程将进入等待状态,直到界面排布完成才会被唤醒,接下来就是重复上面类似的流程加载AllApplist。对应到代码中的加载bind两步走:

//第一步加载WorkSpace,但需要执行部分都通过mHandler.post(new Runnable() 方法放到了主线程的延迟执行队列中。
loadAndBindWorkspace();
//等待主线程空闲,调用this.wait();挂起了launcher-loader线程,UI线程执行Runnable.run单元,直到队列末尾的Idle单元并退出。
waitForIdle();
//再次回到launcher-loader线程,准备并将需要UI线程执行的Bind部分放入延迟执行队列。
loadAndBindAllApps();

4.处理来自系统的广播信息。
         因LauncherModel继承自BroadcastReceiver,那么他将具备处理系统广播的能力,入口为onReceive方法。即模型将负责监控与自身相关系统状态变化(APP卸载、安装、更新,用户配置修改,安装在SD卡上的应用状态,快速搜索图标状态等),接到系统通知后将修改影子容器,切换到UI线程对界面进行更新,最后由launcher-loader线程更新数据到存储设备。
5.界面用户操作修改同步到模型。
         当用户于界面上移动、添加、删除图标完成后,UI线程更新完成影子容器状态后将通知launcher-loader将状态更新到存储介质,这样的闭环保证了界面与模型内数据始终严格的一致。addOrMoveItemInDatabase是我们提供给出来的模型修改接口。
 
去除模型耦合度:
         对象耦合度最小,是增加可复用性与降低维护成本的好方法。模型在Launcher中的地位决定了他必须具备独立且高效两大能力,向下我们通过ContentProvider进行剥离,向上我们通过interface Callbacks将界面构建交给子类实现。
 
让模型更高效的执行:
          使用cache用空间换时间,多线程并发可提高系统效率。通过缓冲需要被界面使用与写入到SQlite中的数据可提高效率,我们分别使用了IconCache与java提供的ArrayList、HashMap(即影子容器)对常用的耗时数据进行缓冲。在模型中使用最频繁的线程为:UI主线程与launcher-loader线程。

<think>好的,我现在需要解决用户提到的Android平台上使用Conscrypt库时出现的javax.net.ssl.SSLHandshakeException: Chain validation failed错误。用户已经提供了之前的回答和一些引用,我需要结合这些信息给出更具体的解决方案。 首先,回顾之前的回答,已经提到了根因分析,包括中间证书缺失、根证书未信任、证书过期和Conscrypt的严格验证策略。解决方案包括强制使用系统信任库、添加自定义证书链和修改Conscrypt配置。用户现在的问题可能是在实施这些方案时遇到了问题,或者需要更多细节。 用户提供的引用中,引用[1]提到了设置系统属性指定信任库的路径,引用[2]则是关于配置TLS连接规范和兼容HTTP。这些信息需要整合到当前的解决方案中,特别是针对Android不同版本的兼容性问题。 接下来,我需要确保回答的结构清晰,分步骤说明解决方案。首先验证证书链完整性,然后考虑系统信任库配置,接着处理中间证书,调整Conscrypt的TLS配置,最后处理自签名证书和调试工具。可能还需要注意Android版本差异和Conscrypt的兼容模式。 需要检查是否有遗漏的步骤,例如如何具体加载自定义证书,或者如何处理Android 7以上的网络安全配置。同时,用户提到的System.setProperty方法可能在Android中不适用,需要调整为适合Android的方式,比如使用自定义TrustManager。 还要考虑用户可能的开发环境,比如使用Kotlin还是Java,但之前的示例中有Kotlin代码,所以保持一致性。同时,引用中的ConnectionSpec配置可能需要结合OkHttp库,需要明确说明。 最后,确保相关问题部分覆盖用户可能遇到的后续问题,例如检测信任证书列表,Conscrypt与其他库的差异,创建证书链等。需要验证每个步骤的可行性和正确性,避免提供错误代码。</think>针对Android平台上使用Conscrypt库时出现的$javax.net.ssl.SSLHandshakeException: Chain\ validation\ failed$异常,以下是结合系统级日志和ConscryptEngine特性的完整解决方案: --- ### 一、证书链验证失败核心原因 1. **中间证书缺失**:服务器未发送完整的证书链 2. **根证书未受信**:设备未预置对应CA证书 3. **证书时间失效**:超过有效期或系统时间异常 4. **Conscrypt严格校验**:Android 9+默认使用Conscrypt引擎的严格证书验证策略[^4] --- ### 二、Android专用解决方案 #### 1. 验证证书链完整性(关键步骤) ```bash # 通过OpenSSL检测服务器证书链 openssl s_client -connect your.domain:443 -servername your.domain -showcerts ``` 若输出中`Verify return code`不为0,需补充缺失的中间证书 #### 2. 强制加载系统信任库(适配Android 7+) ```kotlin val trustManagerFactory = TrustManagerFactory.getInstance("X509") trustManagerFactory.init(null as KeyStore?) // 加载系统默认信任库 val sslContext = SSLContext.getInstance("TLS") sslContext.init(null, trustManagerFactory.trustManagers, null) // 强制Conscrypt使用系统信任库 Conscrypt.setApplicationProtocolSelector(sslContext) { _, _ -> null } ``` #### 3. 处理中间证书缺失(关键代码) ```java // 创建包含中间证书的KeyStore KeyStore customKeystore = KeyStore.getInstance(KeyStore.getDefaultType()); customKeystore.load(null); // 加载中间证书(需将证书文件放在res/raw目录) CertificateFactory cf = CertificateFactory.getInstance("X.509"); InputStream caInput = context.getResources().openRawResource(R.raw.intermediate_ca); Certificate ca = cf.generateCertificate(caInput); customKeystore.setCertificateEntry("intermediate", ca); // 创建混合信任管理器 TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509"); tmf.init(customKeystore); X509TrustManager customTm = (X509TrustManager) tmf.getTrustManagers()[0]; X509TrustManager systemTm = getSystemTrustManager(); // 获取系统默认TrustManager // 创建组合信任管理器 X509TrustManager compositeTm = new X509TrustManager() { @Override public void checkServerTrusted(X509Certificate[] chain, String authType) { try { systemTm.checkServerTrusted(chain, authType); } catch (CertificateException e) { customTm.checkServerTrusted(chain, authType); } } // 其他方法实现... }; ``` #### 4. Conscrypt TLS配置(适配Android 5.0+) ```kotlin // 创建兼容性TLS配置 val spec = ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) .tlsVersions(TlsVersion.TLS_1_3, TlsVersion.TLS_1_2) .cipherSuites( CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ) .build() // 配置OkHttpClient(需依赖okhttp3 4.4+) val client = OkHttpClient.Builder() .connectionSpecs(listOf(spec, ConnectionSpec.CLEARTEXT)) .sslSocketFactory(sslContext.socketFactory, compositeTm) .build() ``` --- ### 三、特殊场景处理 #### 1. 自签名证书场景 ```xml <!-- AndroidManifest.xml添加网络安全配置 --> <network-security-config> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">your.domain</domain> <trust-anchors> <certificates src="@raw/self_signed_cert"/> </trust-anchors> </domain-config> </network-security-config> ``` #### 2. 调试工具 ```java // 启用详细SSL日志(需在Application初始化时调用) Conscrypt.setDebug(true); HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.socketFactory) ``` --- ### 四、注意事项 1. **Android版本差异**:Android 7.0(Nougat)开始强制实施网络安全配置 2. **证书链顺序**:必须按`终端证书 -> 中间CA -> 根CA`顺序排列 3. **Conscrypt兼容模式**:Android 12+需启用`Conscrypt.setUseEngineSocket(true)` 4. **证书指纹验证**:建议补充证书指纹校验作为二次验证 --- ### 五、验证流程 1. 使用`adb logcat | grep -iE 'certificate|ssl'`捕获详细错误 2. 通过[SSL Labs测试](https://www.ssllabs.com/ssltest/)验证服务器配置 3. 用WireShark抓包分析TLS握手过程 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值