前言
上回说到要举一个例子来说明,在看例子前,我们先来说说问题,有时我们会在工作中遇到很难的专业问题,如设计一个业务算法或用OpenGL做3D特效,这类的问题虽然不简单,但属于比较单一的类型。即使出现问题,你也能比较容易集中在特定的领域里去解决它,解决或学习它们的过程中你可能并不需要做太多的选择。
但现实往往会给你一些不一样的问题,总是给你一种不知所措的感觉,有时觉得是自己领域的问题,迷糊中又觉得不是。如我遇到的一个“Access-Control-Allow-Origin”异常问题。
跨域和跨界
我们的APK使用了Cordova框架,在这个框架中加载本地的Html/JS文件,是一个单页Web应用,Web视图上的数据是通过JS发送Http请求从一个提供Rest服务的Tomcat获取。
关于跨域问题可以看到这篇文章:10分钟弄懂跨域资源共享 CORS
问题描叙:
- 在很多手机都是正常的(Android SDK从4.4到7.1),只在某个型号的锤子手机上出现;
- 在出现问题的锤子手机(SM901, SDK 6.0.1, API23)上做测试,发现同是生产版的apk,但Release版和Debug的效果不一样,Release版本会有这个问题,而Debug版本正常。
在问题手机上的截图:
从上面的两点看,你可能会很容易想到是Android的兼容性问题,毕竟这是她的前科不少。
针对第2点,Android Studio默认会为项目构建一个Debug和一个Release版本的应用,这两个版本的不同主要体现在在非开发机上的调试功能以及APK的签名方式,如debuggable属性,在Debug上是true,在其他版本是false。
而且我试过只要把Release的debugable=true,不会出现“Access-Control-Allow-Origin”。
网上也有一些别人试过的做法,如设置"setAllowUniversalAccessFromFileURLs",不过对这个手机还是无效。
新发现
并不是所有的锤子手机都会出现这个问题,我有一台相同型号的手机就没这个问题。但有一次进入“开发这模式”,把“严格模式”打开,在这台手机上重现了这个问题。
不过又引入了新的问题:就算之后我把“严格模式”关闭,在Release版上这个问题仍然出现,关机重启还是能重现。也就是说只要我打开过一次就一直重现,卸载重装还是一样。
逻辑上不能完全说是严格模式引起的,因为严格模式关了还有这个问题(当然,也有可能是厂商的严格模式关闭有BUG)。
再测试发现,把Webview中访问的Url换成其他的(如github.com)并不会报Access-Control-Allow-Origin的错误,那么问题是服务端了?
技术的本质
了解了一下,这个项目的前后端构建,大体涉及的技术节点如下:
我们不妨问一下我们自己,这个是Android端的问题、前端的问题,还是后端的问题?
如果是移动端,我们可能就局限在兼容性的问题上了,可能需在Android更深入的知识或者咨询锤子手机的专家。如果在前端或者后端,可能也需要他们对移动端也有部分了解。
这只是一个具体的案例,这个问题你可以按手机的兼容性去解决,也可以从前端、Nginx和Java后端去寻求其他的解决方案。
而我们可能也有所察觉,新技术都是建立在多个已有技术的组合之上的。技术并不是凭空产生的,而且通过不同的组合衍生的。这个案例虽然看似不复杂,但却涉及前后端来配合查找方案,势必就会涉及多个技术栈。
取舍
这个问题最终怎么解决呢?
其实,我没有解决,取舍如下(理解成借口也成立):
- 我可以通过非技术手段绕过这个问题;
- 我有更有价值的事情要去完成;
不过我还是很感兴趣花时间去看一下跨域和Nginx方面的一些知识。
我们解决问题不一定非要局限于自己熟悉的领域,我们可以尝试各种正常和“不正常”的方式,但需要从几个方面进行取舍:
- 这真的是问题吗?
- 解决这个问题的成本高吗?
- 解决这个问题的对自己和公司有多大的价值?
- 除了技术的解决方案,没有其他的选择吗?
很多时候追问第一个问题会发现,你遇到的很多问题都不需要解决,或者可以用非技术方案解决。还有很多问题因为你有更合适的技术栈,或者可以咨询或得到这方面的帮助,能让你用更优雅简洁的方案解决。
这也是我慢慢在转变的方向,单一的技术慢慢变成爱好。真正要做好事情,还需要我们给自更加拥抱变化和未知的机会。技术重要,但有更多的技术组合能让你产生更大的价值。
并在这个过程感受到了新的东西,发现一些秘密:
我们一直以为自己在解决技术问题,其实我们面临的是沟通问题。