首页 文章 精选 留言 我的

精选列表

搜索[官方],共10000篇文章
优秀的个人博客,低调大师

SAP官方到底提供了免费的S4HANA试用版没有?

经常有朋友在微信公众号上给我留言,询问是否有免费的S/4HANA系统可以用。 作为SAP员工,我能给的答复就是这篇SAP社区的博客: SAP S/4HANA Fully-Activated Appliance: Create your SAP S/4HANA system in a fraction of the usual setup time https://blogs.sap.com/2018/12/12/sap-s4hana-fully-activated-appliance-create-your-sap-s4hana-1809-system-in-a-fraction-of-the-usual-setup-time/ 博客标题里提到的Appliance是什么意思? The appliance is a compressed system image that contains an SAP S/4HANA system with pre-configured SAP Best Practices and demo scenarios. 一个压缩之后的系统镜像,包含预先配置好了SAP最佳实践和演示场景的S/4HANA系统。 对于看过《异形》系列的朋友们来说,可以把S/4HANA appliance类比成异形的蛋(学名叫Ovomorph). 在《异形》系列影片里,有不止一位生物科学家赞叹过异形,惊叹于这种生命物种的纯粹和超高的攻击和防御力。科学家们认为异形是一种完美的生物。而通过S/4HANA appliance孵化出的S/4HANA系统,具有最纯正的蓝色软件巨人的血统,作为SAP R/3之后的下一代商务套件,在内存计算,物联网,人工智能,大数据实现的人、设备和业务网络的实时互联等方面都有突出进展,是客户在数字化时代加速实现企业卓越运营的完美助手。 该Appliance可以通过SAP CAL(Cloud Appliance Library), 在一到两个小时之内部署到AWS, Azure或者Google Cloud Platform上,孵化出可用的S/4HANA系统。当然,On-Premises的孵化方式也仍旧支持,部署到客户本地的物理服务器上,需要花费两到三天。 通过appliance孵化出的S/4HANA系统,只能用于测试,原型验证和开发等,不能用于正式的生产用途。 使用这个链接开始试用: https://www.sap.com/registration/trial.b29aeae9-94b4-4e44-8d7e-fe3acbaab116.html 点击Start your 30-day trial之后,在弹出的窗口里维护注册必需的字段: 该appliance可以免费试用30天。注册成功后会收到一封邮件,里面包含了能够操作申请的用于测试用途的S/4HANA appliance的CAL url. 登录之后,从Cloud Provider下拉列表里选择AWS,GCP或者Azure,然后就可以在这些云平台上把S/4HANA appliance孵化成可用的S/4HANA系统。 这也就是SAP如今在很多云服务使用场景里都提到的BYOL概念 - Bring Your Own License. 回到本文的上下文,S/4HANA trial appliance本身是30天免费使用的,但因为孵化后的S/4HANA系统是运行在AWS, Azure或者GCP上,因此使用者需要事先在这三个云服务平台之一上面拥有帐号,且需要按照实际使用情况,向AWS,Azure或GCP支付使用费用。 包括之前Jerry文章介绍的SAP Cloud Platform Extension Factory的计费方式,也是按照BYOL进行的。 将这三大云平台上帐号的明细维护到CAL里,点击Create即可创建实例。 可以使用Calculate Cost按钮,选择不同的硬件资源,然后查看预估的使用费用: 以AWS为例,最低配的价格每小时2.69美元。 各位,想试试吗? (题图:从蛋里孵化出来,集合了众多龙珠战士细胞的超强BOSS:沙鲁) 本文来自云栖社区合作伙伴“汪子熙”,了解相关信息可以关注微信公众号"汪子熙"。

优秀的个人博客,低调大师

《JDK10新特性官方文档》从JDK10中移除javah工具

JEP 313: 移除Native-Header生成工具 (javah) Owner Jonathan Gibbons Created 2017/06/23 17:28 Updated 2018/01/10 22:02 Type Feature Status Closed / Delivered Component tools / javah Scope JDK Discussion compiler dash dev at openjdk dot java dot net Effort XS Priority 3 Reviewed by Brian Goetz, Joe Darcy Endorsed by Brian Goetz Release 10 Issue 8182758 概要 从JDK中移除javah工具。 动机 该工具已被JDK 8(JDK-7150368)中添加在javac的高级功能替代。此功能提供了在编译Java源码时生成本地头文件的功能,因此无需使用单独工具。 专注于javac提供的支持,对最近的新范例支持,无需升级javah,例如通过javax.tools.*中的编译API进行API访问,以及在JDK 9中添加新的java.util.spi.ToolProvider SPI。 描述 删除操作将包括从Mercurial仓库中删除受影响的文件,包括文档,以及makefile 文件的修改。 测试 所有测试将仅限于验证javah命令是否移除干净。 风险和前提 将javah从JDK中删除没有任何工程问题,因为JDK使用不再使用该工具,构建JDK时也未使用。 JDK 9开始,用户已被警告待执行的删除操作,这些警告在每次调用javah工具时都会被触发。 依赖 javah工具和JDK没有直接依赖关系。而且正如javah命令的用户被推荐使用javac -h一样,javah的一些衍生产品,比如Ant javah,使用这些任务依赖关系的用户,也被推荐使用javac提供相应的支持。 原文发布时间为:2018-05-22 本文来自云栖社区合作伙伴“并发编程网 - ifeve.com”,了解相关信息可以关注“并发编程网 - ifeve.com”。

优秀的个人博客,低调大师

Tensorflow官方语音识别入门教程 | 附Google新语音指令数据集

本文来自AI新媒体量子位(QbitAI) Google今天推出了一个语音指令数据集,其中包含30个词的65000条语音,wav格式,每条长度为一秒钟。 这30个词都是英文的,基本是yes、no、up、down、stop、go这类。 这个数据集由Google TensorFlow团队和AIY团队共同推出的,AIY就是之前推出树莓派DIY智能音箱的那个团队: 所以说,也别指望用这个数据集训练模型然后做个App什么的,它其实和那个DIY的音箱差不多,主要供初学者/爱好者练手用。 语音识别教程 Google还配合这个数据集,推出了一份TensorFlow教程,教你训练一个简单的语音识别网络,能识别10个词,就像是语音识别领域的MNIST(手写数字识别数据集)。 虽然这份教程和数据集都比真实场景简化了太多,但能帮用户建立起对语音识别技术的基本理解,很适合

优秀的个人博客,低调大师

android app性能优化大汇总(google官方Android性能优化典范 - 第1季)

大多数用户感知到的卡顿等性能问题的最主要根源都是因为渲染性能。从设计师的角度,他们希望App能够有更多的动画,图片等时尚元素来实现流畅的用户体验。但是Android系统很有可能无法及时完成那些复杂的界面渲染操作。Android系统每隔16ms发出VSYNC信号,触发对UI进行渲染,如果每次渲染都成功,这样就能够达到流畅的画面所需要的60fps,为了能够实现60fps,这意味着程序的大多数操作都必须在16ms内完成。 如果你的某个操作花费时间是24ms,系统在得到VSYNC信号的时候就无法进行正常渲染,这样就发生了丢帧现象。那么用户在32ms内看到的会是同一帧画面。 用户容易在UI执行动画或者滑动ListView的时候感知到卡顿不流畅,是因为这里的操作相对复杂,容易发生丢帧的现象,从而感觉卡顿。有很多原因可以导致丢帧,也许是因为你的layout太过复杂,无法在16ms内完成渲染,有可能是因为你的UI上有层叠太多的绘制单元,还有可能是因为动画执行的次数过多。这些都会导致CPU或者GPU负载过重。 我们可以通过一些工具来定位问题,比如可以使用HierarchyViewer来查找Activity中的布局是否过于复杂,也可以使用手机设置里面的开发者选项,打开Show GPU Overdraw等选项进行观察。你还可以使用TraceView来观察CPU的执行情况,更加快捷的找到性能瓶颈。 (a)Understanding Overdraw Overdraw(过度绘制)描述的是屏幕上的某个像素在同一帧的时间内被绘制了多次。在多层次的UI结构里面,如果不可见的UI也在做绘制的操作,这就会导致某些像素区域被绘制了多次。这就浪费大量的CPU以及GPU资源。 当设计上追求更华丽的视觉效果的时候,我们就容易陷入采用越来越多的层叠组件来实现这种视觉效果的怪圈。这很容易导致大量的性能问题,为了获得最佳的性能,我们必须尽量减少Overdraw的情况发生。 幸运的是,我们可以通过手机设置里面的开发者选项,打开Show GPU Overdraw的选项,可以观察UI上的Overdraw情况。 蓝色,淡绿,淡红,深红代表了4种不同程度的Overdraw情况,我们的目标就是尽量减少红色Overdraw,看到更多的蓝色区域。 Overdraw有时候是因为你的UI布局存在大量重叠的部分,还有的时候是因为非必须的重叠背景。例如某个Activity有一个背景,然后里面的Layout又有自己的背景,同时子View又分别有自己的背景。仅仅是通过移除非必须的背景图片,这就能够减少大量的红色Overdraw区域,增加蓝色区域的占比。这一措施能够显著提升程序性能。 (b)Understanding VSYNC 为了理解App是如何进行渲染的,我们必须了解手机硬件是如何工作,那么就必须理解什么是VSYNC。 在讲解VSYNC之前,我们需要了解两个相关的概念: Refresh Rate:代表了屏幕在一秒内刷新屏幕的次数,这取决于硬件的固定参数,例如60Hz。 Frame Rate:代表了GPU在一秒内绘制操作的帧数,例如30fps,60fps。 GPU会获取图形数据进行渲染,然后硬件负责把渲染后的内容呈现到屏幕上,他们两者不停的进行协作。 不幸的是,刷新频率和帧率并不是总能够保持相同的节奏。如果发生帧率与刷新频率不一致的情况,就会容易出现Tearing的现象(画面上下两部分显示内容发生断裂,来自不同的两帧数据发生重叠)。 理解图像渲染里面的双重与三重缓存机制,这个概念比较复杂,请移步查看这里:http://source.android.com/devices/graphics/index.html,还有这里http://article.yeeyan.org/view/37503/304664。 通常来说,帧率超过刷新频率只是一种理想的状况,在超过60fps的情况下,GPU所产生的帧数据会因为等待VSYNC的刷新信息而被Hold住,这样能够保持每次刷新都有实际的新的数据可以显示。但是我们遇到更多的情况是帧率小于刷新频率。 在这种情况下,某些帧显示的画面内容就会与上一帧的画面相同。糟糕的事情是,帧率从超过60fps突然掉到60fps以下,这样就会发生LAG,JANK,HITCHING等卡顿掉帧的不顺滑的情况。这也是用户感受不好的原因所在。 (c)Tool:Profile GPU Rendering 性能问题如此的麻烦,幸好我们可以有工具来进行调试。打开手机里面的开发者选项,选择Profile GPU Rendering,选中On screen as bars的选项。 选择了这样以后,我们可以在手机画面上看到丰富的GPU绘制图形信息,分别关于StatusBar,NavBar,激活的程序Activity区域的GPU Rending信息。 随着界面的刷新,界面上会滚动显示垂直的柱状图来表示每帧画面所需要渲染的时间,柱状图越高表示花费的渲染时间越长。 中间有一根绿色的横线,代表16ms,我们需要确保每一帧花费的总时间都低于这条横线,这样才能够避免出现卡顿的问题。 每一条柱状线都包含三部分,蓝色代表测量绘制Display List的时间,红色代表OpenGL渲染Display List所需要的时间,×××代表CPU等待GPU处理的时间。 (d)Why 60fps? 我们通常都会提到60fps与16ms,可是知道为何会是以程序是否达到60fps来作为App性能的衡量标准吗?这是因为人眼与大脑之间的协作无法感知超过60fps的画面更新。 12fps大概类似手动快速翻动书籍的帧率,这明显是可以感知到不够顺滑的。24fps使得人眼感知的是连续线性的运动,这其实是归功于运动模糊的效果。24fps是电影胶圈通常使用的帧率,因为这个帧率已经足够支撑大部分电影画面需要表达的内容,同时能够最大的减少费用支出。但是低于30fps是无法顺畅表现绚丽的画面内容的,此时就需要用到60fps来达到想要的效果,当然超过60fps是没有必要的。 开发app的性能目标就是保持60fps,这意味着每一帧你只有16ms=1000/60的时间来处理所有的任务。 (e)Android, UI and the GPU 了解Android是如何利用GPU进行画面渲染有助于我们更好的理解性能问题。那么一个最实际的问题是:activity的画面是如何绘制到屏幕上的?那些复杂的XML布局文件又是如何能够被识别并绘制出来的? Resterization栅格化是绘制那些Button,Shape,Path,String,Bitmap等组件最基础的操作。它把那些组件拆分到不同的像素上进行显示。这是一个很费时的操作,GPU的引入就是为了加快栅格化的操作。 CPU负责把UI组件计算成Polygons,Texture纹理,然后交给GPU进行栅格化渲染。 然而每次从CPU转移到GPU是一件很麻烦的事情,所幸的是OpenGL ES可以把那些需要渲染的纹理Hold在GPU Memory里面,在下次需要渲染的时候直接进行操作。所以如果你更新了GPU所hold住的纹理内容,那么之前保存的状态就丢失了。 在Android里面那些由主题所提供的资源,例如Bitmaps,Drawables都是一起打包到统一的Texture纹理当中,然后再传递到GPU里面,这意味着每次你需要使用这些资源的时候,都是直接从纹理里面进行获取渲染的。当然随着UI组件的越来越丰富,有了更多演变的形态。例如显示图片的时候,需要先经过CPU的计算加载到内存中,然后传递给GPU进行渲染。文字的显示更加复杂,需要先经过CPU换算成纹理,然后再交给GPU进行渲染,回到CPU绘制单个字符的时候,再重新引用经过GPU渲染的内容。动画则是一个更加复杂的操作流程。 为了能够使得App流畅,我们需要在每一帧16ms以内处理完所有的CPU与GPU计算,绘制,渲染等等操作。 (f)Invalidations, Layouts, and Performance 顺滑精妙的动画是app设计里面最重要的元素之一,这些动画能够显著提升用户体验。下面会讲解Android系统是如何处理UI组件的更新操作的。 通常来说,Android需要把XML布局文件转换成GPU能够识别并绘制的对象。这个操作是在DisplayList的帮助下完成的。DisplayList持有所有将要交给GPU绘制到屏幕上的数据信息。 在某个View第一次需要被渲染时,DisplayList会因此而被创建,当这个View要显示到屏幕上时,我们会执行GPU的绘制指令来进行渲染。如果你在后续有执行类似移动这个View的位置等操作而需要再次渲染这个View时,我们就仅仅需要额外操作一次渲染指令就够了。然而如果你修改了View中的某些可见组件,那么之前的DisplayList就无法继续使用了,我们需要回头重新创建一个DisplayList并且重新执行渲染指令并更新到屏幕上。 需要注意的是:任何时候View中的绘制内容发生变化时,都会重新执行创建DisplayList,渲染DisplayList,更新到屏幕上等一系列操作。这个流程的表现性能取决于你的View的复杂程度,View的状态变化以及渲染管道的执行性能。举个例子,假设某个Button的大小需要增大到目前的两倍,在增大Button大小之前,需要通过父View重新计算并摆放其他子View的位置。修改View的大小会触发整个HierarcyView的重新计算大小的操作。如果是修改View的位置则会触发HierarchView重新计算其他View的位置。如果布局很复杂,这就会很容易导致严重的性能问题。我们需要尽量减少Overdraw。 我们可以通过前面介绍的Monitor GPU Rendering来查看渲染的表现性能如何,另外也可以通过开发者选项里面的Show GPU view updates来查看视图更新的操作,最后我们还可以通过HierarchyViewer这个工具来查看布局,使得布局尽量扁平化,移除非必需的UI组件,这些操作能够减少Measure,Layout的计算时间。 (g)Overdraw, Cliprect, QuickReject 引起性能问题的一个很重要的方面是因为过多复杂的绘制操作。我们可以通过工具来检测并修复标准UI组件的Overdraw问题,但是针对高度自定义的UI组件则显得有些力不从心。 有一个窍门是我们可以通过执行几个APIs方法来显著提升绘制操作的性能。前面有提到过,非可见的UI组件进行绘制更新会导致Overdraw。例如Nav Drawer从前置可见的Activity滑出之后,如果还继续绘制那些在Nav Drawer里面不可见的UI组件,这就导致了Overdraw。为了解决这个问题,Android系统会通过避免绘制那些完全不可见的组件来尽量减少Overdraw。那些Nav Drawer里面不可见的View就不会被执行浪费资源。 但是不幸的是,对于那些过于复杂的自定义的View(重写了onDraw方法),Android系统无法检测具体在onDraw里面会执行什么操作,系统无法监控并自动优化,也就无法避免Overdraw了。但是我们可以通过canvas.clipRect()来帮助系统识别那些可见的区域。这个方法可以指定一块矩形区域,只有在这个区域内才会被绘制,其他的区域会被忽视。这个API可以很好的帮助那些有多组重叠组件的自定义View来控制显示的区域。同时clipRect方法还可以帮助节约CPU与GPU资源,在clipRect区域之外的绘制指令都不会被执行,那些部分内容在矩形区域内的组件,仍然会得到绘制。 除了clipRect方法之外,我们还可以使用canvas.quickreject()来判断是否没和某个矩形相交,从而跳过那些非矩形区域内的绘制操作。做了那些优化之后,我们可以通过上面介绍的Show GPU Overdraw来查看效果。 (h)Memory Churn and performance 虽然Android有自动管理内存的机制,但是对内存的不恰当使用仍然容易引起严重的性能问题。在同一帧里面创建过多的对象是件需要特别引起注意的事情。 Android系统里面有一个Generational Heap Memory的模型,系统会根据内存中不同的内存数据类型分别执行不同的GC操作。例如,最近刚分配的对象会放在Young Generation区域,这个区域的对象通常都是会快速被创建并且很快被销毁回收的,同时这个区域的GC操作速度也是比Old Generation区域的GC操作速度更快的。 除了速度差异之外,执行GC操作的时候,所有线程的任何操作都会需要暂停,等待GC操作完成之后,其他操作才能够继续运行。 通常来说,单个的GC并不会占用太多时间,但是大量不停的GC操作则会显著占用帧间隔时间(16ms)。如果在帧间隔时间里面做了过多的GC操作,那么自然其他类似计算,渲染等操作的可用时间就变得少了。 导致GC频繁执行有两个原因: Memory Churn内存抖动,内存抖动是因为大量的对象被创建又在短时间内马上被释放。 瞬间产生大量的对象会严重占用Young Generation的内存区域,当达到阀值,剩余空间不够的时候,也会触发GC。即使每次分配的对象占用了很少的内存,但是他们叠加在一起会增加Heap的压力,从而触发更多其他类型的GC。这个操作有可能会影响到帧率,并使得用户感知到性能问题。 解决上面的问题有简洁直观方法,如果你在Memory Monitor里面查看到短时间发生了多次内存的涨跌,这意味着很有可能发生了内存抖动。 同时我们还可以通过Allocation Tracker来查看在短时间内,同一个栈中不断进出的相同对象。这是内存抖动的典型信号之一。 当你大致定位问题之后,接下去的问题修复也就显得相对直接简单了。例如,你需要避免在for循环里面分配对象占用内存,需要尝试把对象的创建移到循环体之外,自定义View中的onDraw方法也需要引起注意,每次屏幕发生绘制以及动画执行过程中,onDraw方法都会被调用到,避免在onDraw方法里面执行复杂的操作,避免创建对象。对于那些无法避免需要创建对象的情况,我们可以考虑对象池模型,通过对象池来解决频繁创建与销毁的问题,但是这里需要注意结束使用之后,需要手动释放对象池中的对象。 (i)Garbage Collection in Android JVM的回收机制给开发人员带来很大的好处,不用时刻处理对象的分配与回收,可以更加专注于更加高级的代码实现。相比起Java,C与C++等语言具备更高的执行效率,他们需要开发人员自己关注对象的分配与回收,但是在一个庞大的系统当中,还是免不了经常发生部分对象忘记回收的情况,这就是内存泄漏。 原始JVM中的GC机制在Android中得到了很大程度上的优化。Android里面是一个三级Generation的内存模型,最近分配的对象会存放在Young Generation区域,当这个对象在这个区域停留的时间达到一定程度,它会被移动到Old Generation,最后到Permanent Generation区域。 每一个级别的内存区域都有固定的大小,此后不断有新的对象被分配到此区域,当这些对象总的大小快达到这一级别内存区域的阀值时,会触发GC的操作,以便腾出空间来存放其他新的对象。 前面提到过每次GC发生的时候,所有的线程都是暂停状态的。GC所占用的时间和它是哪一个Generation也有关系,Young Generation的每次GC操作时间是最短的,Old Generation其次,Permanent Generation最长。执行时间的长短也和当前Generation中的对象数量有关,遍历查找20000个对象比起遍历50个对象自然是要慢很多的。 虽然Google的工程师在尽量缩短每次GC所花费的时间,但是特别注意GC引起的性能问题还是很有必要。如果不小心在最小的for循环单元里面执行了创建对象的操作,这将很容易引起GC并导致性能问题。通过Memory Monitor我们可以查看到内存的占用情况,每一次瞬间的内存降低都是因为此时发生了GC操作,如果在短时间内发生大量的内存上涨与降低的事件,这说明很有可能这里有性能问题。我们还可以通过Heap and Allocation Tracker工具来查看此时内存中分配的到底有哪些对象。 (j)Performance Cost of Memory Leaks 虽然Java有自动回收的机制,可是这不意味着Java中不存在内存泄漏的问题,而内存泄漏会很容易导致严重的性能问题。 内存泄漏指的是那些程序不再使用的对象无法被GC识别,这样就导致这个对象一直留在内存当中,占用了宝贵的内存空间。显然,这还使得每级Generation的内存区域可用空间变小,GC就会更容易被触发,从而引起性能问题。 寻找内存泄漏并修复这个漏洞是件很棘手的事情,你需要对执行的代码很熟悉,清楚的知道在特定环境下是如何运行的,然后仔细排查。例如,你想知道程序中的某个activity退出的时候,它之前所占用的内存是否有完整的释放干净了?首先你需要在activity处于前台的时候使用Heap Tool获取一份当前状态的内存快照,然后你需要创建一个几乎不这么占用内存的空白activity用来给前一个Activity进行跳转,其次在跳转到这个空白的activity的时候主动调用System.gc()方法来确保触发一个GC操作。最后,如果前面这个activity的内存都有全部正确释放,那么在空白activity被启动之后的内存快照中应该不会有前面那个activity中的任何对象了。 如果你发现在空白activity的内存快照中有一些可疑的没有被释放的对象存在,那么接下去就应该使用Alocation Track Tool来仔细查找具体的可疑对象。我们可以从空白activity开始监听,启动到观察activity,然后再回到空白activity结束监听。这样操作以后,我们可以仔细观察那些对象,找出内存泄漏的真凶。 (k)Memory Performance 通常来说,Android对GC做了大量的优化操作,虽然执行GC操作的时候会暂停其他任务,可是大多数情况下,GC操作还是相对很安静并且高效的。但是如果我们对内存的使用不恰当,导致GC频繁执行,这样就会引起不小的性能问题。 为了寻找内存的性能问题,Android Studio提供了工具来帮助开发者。 Memory Monitor:查看整个app所占用的内存,以及发生GC的时刻,短时间内发生大量的GC操作是一个危险的信号。 Allocation Tracker:使用此工具来追踪内存的分配,前面有提到过。 Heap Tool:查看当前内存快照,便于对比分析哪些对象有可能是泄漏了的,请参考前面的Case。 (l)Tool - Memory Monitor Android Studio中的Memory Monitor可以很好的帮助我们查看程序的内存使用情况。 (m)Battery Performance 电量其实是目前手持设备最宝贵的资源之一,大多数设备都需要不断的充电来维持继续使用。不幸的是,对于开发者来说,电量优化是他们最后才会考虑的的事情。但是可以确定的是,千万不能让你的应用成为消耗电量的大户。 Purdue University研究了最受欢迎的一些应用的电量消耗,平均只有30%左右的电量是被程序最核心的方法例如绘制图片,摆放布局等等所使用掉的,剩下的70%左右的电量是被上报数据,检查位置信息,定时检索后台广告信息所使用掉的。如何平衡这两者的电量消耗,就显得非常重要了。 有下面一些措施能够显著减少电量的消耗: 我们应该尽量减少唤醒屏幕的次数与持续的时间,使用WakeLock来处理唤醒的问题,能够正确执行唤醒操作并根据设定及时关闭操作进入睡眠状态。 某些非必须马上执行的操作,例如上传歌曲,图片处理等,可以等到设备处于充电状态或者电量充足的时候才进行。 触发网络请求的操作,每次都会保持无线信号持续一段时间,我们可以把零散的网络请求打包进行一次操作,避免过多的无线信号引起的电量消耗。关于网络请求引起无线信号的电量消耗,还可以参考这里http://hukai.me/android-training-course-in-chinese/connectivity/efficient-downloads/efficient-network-access.html 我们可以通过手机设置选项找到对应App的电量消耗统计数据。我们还可以通过Battery Historian Tool来查看详细的电量消耗。 如果发现我们的App有电量消耗过多的问题,我们可以使用JobScheduler API来对一些任务进行定时处理,例如我们可以把那些任务重的操作等到手机处于充电状态,或者是连接到WiFi的时候来处理。 关于JobScheduler的更多知识可以参考http://hukai.me/android-training-course-in-chinese/background-jobs/scheduling/index.html (n)Understanding Battery Drain on Android 高效的保留更多的电量与不断促使用户使用你的App会消耗电量,这是矛盾的选择题。不过我们可以使用一些更好的办法来平衡两者。 假设你的手机里面装了大量的社交类应用,即使手机处于待机状态,也会经常被这些应用唤醒用来检查同步新的数据信息。Android会不断关闭各种硬件来延长手机的待机时间,首先屏幕会逐渐变暗直至关闭,然后CPU进入睡眠,这一切操作都是为了节约宝贵的电量资源。但是即使在这种睡眠状态下,大多数应用还是会尝试进行工作,他们将不断的唤醒手机。一个最简单的唤醒手机的方法是使用PowerManager.WakeLock的API来保持CPU工作并防止屏幕变暗关闭。这使得手机可以被唤醒,执行工作,然后回到睡眠状态。知道如何获取WakeLock是简单的,可是及时释放WakeLock也是非常重要的,不恰当的使用WakeLock会导致严重错误。例如网络请求的数据返回时间不确定,导致本来只需要10s的事情一直等待了1个小时,这样会使得电量白白浪费了。这也是为何使用带超时参数的wakelock.acquice()方法是很关键的。但是仅仅设置超时并不足够解决问题,例如设置多长的超时比较合适?什么时候进行重试等等? 解决上面的问题,正确的方式可能是使用非精准定时器。通常情况下,我们会设定一个时间进行某个操作,但是动态修改这个时间也许会更好。例如,如果有另外一个程序需要比你设定的时间晚5分钟唤醒,最好能够等到那个时候,两个任务捆绑一起同时进行,这就是非精确定时器的核心工作原理。我们可以定制计划的任务,可是系统如果检测到一个更好的时间,它可以推迟你的任务,以节省电量消耗。 这正是JobScheduler API所做的事情。它会根据当前的情况与任务,组合出理想的唤醒时间,例如等到正在充电或者连接到WiFi的时候,或者集中任务一起执行。我们可以通过这个API实现很多免费的调度算法。 从Android 5.0开始发布了Battery History Tool,它可以查看程序被唤醒的频率,又谁唤醒的,持续了多长的时间,这些信息都可以获取到。 请关注程序的电量消耗,用户可以通过手机的设置选项观察到那些耗电量大户,并可能决定卸载他们。所以尽量减少程序的电量消耗是非常有必要的。 http://www.cnblogs.com/yezhennan/p/5431738.html 本文转自 知止内明 51CTO博客,原文链接:http://blog.51cto.com/357712148/2046041,如需转载请自行联系原作者

优秀的个人博客,低调大师

Instant App 常见问题官方指南 | Android 开发者 FAQ Vol.6

我们被大家的热情惊到了 —— 事实上我们发出上一篇 Instant App 的文章没几天就收到了一大堆问题。由于涉及到的类目太多,我们这里简单归纳了一下,方便大家查看。如果还有更多问题也请随时通过留言的方式与我们取得联系。 1. 基础类问题 Q: 哪些设备兼容 Android Instant App? A: Android Instant App 在运行 Android 6.0(API 级别 23)或更高版本的设备上可用,此外还计划为 Android 5.0(API 级别 21)添加额外的支持。例如,现在您可以在 Google Pixel、Google Nexus、Samsung Galaxy S7 等人气设备上开发 Instant App。 Q: 哪些国家和地区支持 Android Instant App? A: 您可以在支持页面中找到完整的支持国家和地区列表: (https://support.google.com/googleplay/android-developer/answer/7381861#production) Q: 开发者现在需要构建两套不同的 Android 应用吗? A: 正相反,开发者只需使用一个源代码树维护一个项目即可。通过对项目进行配置,创造出两套架构工件:可安装版本和免安装版本。在可安装应用基础上添加免安装支持需要的工作量大小取决于可安装应用的当前架构。 * 请注意,免安装应用的版本号必须等于或小于上次发布的可安装应用版本。 Q: Instant App 都能使用什么 Android API 和功能? A: Android Instant App 设计的目的是扩展现存 App 的使用场景,而非取代它们。所以Android Instant App 使用同样的 Android API,同样的项目,同样的源代码。当然,由于Android Instant App 的 “免安装” 特性,可能会无法符合用户针对 “已安装” 应用所抱有的一些期待。例如,免安装应用无法使用后台服务,无法激活后台通知,也无法使用设备唯一标识符。 Q: 用户可以选择永久安装应用吗? A: 当然!开发者可以允许用户从 Google Play 安装应用。在安装完成后,当用户离开应用时,它仍会留在用户的手机上 —— 就和现在大家正在做的事情一样。 Q: Android Instant App 的权限需求是怎样的? A: Android Instant App 使用自 Android 6.0 (API 级别 23)以来采用的运行时权限。 Q: 免安装应用可以获取哪些权限? A:免安装应用可以使用下列 Android 权限。没有出现在下方列表中的权限将无法在免安装应用中使用。 BILLING ACCESS_COARSE_LOCATION ACCESS_FINE_LOCATION ACCESS_NETWORK_STATE CAMERA INSTANT_APP_FOREGROUND_SERVICE 仅限 Android O INTERNET READ_PHONE_NUMBERS 仅限 Android O RECORD_AUDIO VIBRATE Q:免安装应用对网络访问有哪些限制? A:来自免安装应用的一切网络流量均必须使用 HTTPS,不支持 HTTP。 Q:开发者要如何发布这些应用? A:开发者需要经由 Google Play Console 发布免安装应用,这一点与现有的 Android 应用并无两样。想要了解更多信息,请参阅 “发布您的免安装应用” : (https://support.google.com/googleplay/android-developer/answer/7381861) Q:免安装应用必须使用 Smart Lock 么? A:是的,我们规定在免安装中的登录体验必须使用 Smart Lock。想要进一步了解如何在应用中使用 Smart Lock,请参阅 “为您的 Android 密码使用 Smart Lock” : (https://developers.google.cn/identity/smartlock-passwords/android/) Q:我能不能在没有可安装版本 Android 应用的情况下实现一个免安装应用? A:不能。您必须首先在 Google Play 中拥有一个该 App 的可安装版本。 Q:我们能在里面使用 WebP 图片格式吗? A:当然可以,我们推荐使用 WebP 格式的图片。想要了解更多信息,请参阅 “如何缩减下载图片的大小” : (https://developer.android.google.cn/topic/performance/network-xfer.html#webp) Q:免安装应用在 Google 网页搜索中将会如何呈现? A:免安装应用与可安装应用的搜索显示结果并无不同。在搜索结果中,免安装应用会显示出应用图标,如果该 URL 已与免安装应用相关联,则还会显示 “Instant” 标签,正如搜索结果中的可安装应用会在图标上显示 “Installed” 标签一样。 Q:我能使用 Android Instant App 的形式来承载我的游戏吗? A:游戏是极为特别的一类应用,它们通常拥有独特的工具库和庞大的资产库,对性能表现的要求也很高。即使如此,我们对探索游戏用户的使用案例也充满兴趣。请前往 StackOverflow 浏览有关 Android Instant App 的帖子,不少人也在讨论这个话题。 2. 项目结构、功能和架构 Q:免安装应用和可安装应用是否拥有不同的 build.gradle 文件? A:如果您的可安装应用和免安装应用来自同一个 Android Studio 项目,那么答案是肯定的,两种应用需要不同的 build.gradle 文件。您必须使用符合 com.android.application 构建规则的模块来构建您的可安装应用,而当您构建免安装应用时则需要使用符合 com.android.instantapp 构建规则的模块。想要了解更多信息,请参阅 “项目结构” : (https://developer.android.google.cn/topic/instant-apps/getting-started/structure.html#structure_of_a_basic_instant_app) Q:我能独立编译可安装与免安装应用吗? A:正如上面 “项目结构” 中所展示的那样,我们推荐采用的工程结构应该优先将独立的功能封装成模块,这样可安装应用和免安装应用都可以依赖这些库模块。如果您遵循我们推荐的工程结构,您就可以独立编译每个功能而不涉及其他。 Q:我应该如何在免安装应用中的不同页面之间进行导航? A:您可以通过进入一条目标页面的 URL 来导航过去。由于这个原因,免安装应用中的页面均需满足这个条件:可被 URL 寻址。想要了解更多如何让app页面可被 URL 寻址的内容,请参阅 “如何从 Google Play 请求功能” : (https://developer.android.google.cn/topic/instant-apps/overview.html#play_store) 和 “实现应用链接” : (https://developer.android.google.cn/topic/instant-apps/getting-started/index.html#app-links) Q:我能在我的主应用里处理深度链接(Deep Link),然后再调用其他免安装应用的页面吗? A:免安装应用需要在功能上实现模块化,通过主应用集中处理与此相矛盾。使用 App Link 即可进行您需要的链接跳转功能,同时保持免安装应用的模块化特性。 Q:我能在一个功能内包含多个页面吗? A:您可以在一个功能内包含多个页面。但您需要留意的是,免安装应用下载有 4MB 的大小限制。同时,每个功能都需要用一个页面作为入口。 Q:我能在不同功能之间共享资源吗? A:可以,基本功能(Base Feature)内的资源可以被所有功能分享。包含在附加功能之内的资源则只能被这个功能所使用。想要了解更多关于如何搭建您的项目资源,以及如何在不同功能之间共享资源,请参阅上面提到的 “项目结构”。 额外再说一点,您必须把位于附加功能和基本功能之间的资源 ID 区分开来。例如,如果您的基本功能提供了一个名为 R.id.feature_layout 的资源 ID,但您的附加功能却定义了另一个同 ID 资源,那么免安装应用就会使用来自基本功能的资源,而不会使用来自附加功能的资源。 此外,所有随着功能模块的产生而被引用的资源都必须在基本功能模块内出现。 Q:如果应用内有两个功能,它们是否会共享存储? A:会,多个功能会在同一进程中运行,并共享应用上下文,只要它们属于同一个免安装应用。但是,免安装应用相较于可安装 APK 而言拥有一些限制。想要了解更多信息,请参阅 “了解受限和不受支持的功能” : (https://developer.android.google.cn/topic/instant-apps/prepare.html#restricted) Q:我能在同一页面内的 view-pager 中拥有多个分段(Fragment)吗? A:可以,您能在单一页面中拥有多个分段,并在功能内定义与页面相关的分段。但请记住分段不能与深链接相关,并且不能独立于页面启动。 Q:免安装应用应该拥有独立的应用图标吗? A:不,免安装应用和可安装应用应该使用同一个图标。可安装应用和免安装应用应该为用户提供一致的体验,因此它们应该使用同样的视觉元素(如图标)。 想要了解更多关于如何关联免安装应用和可安装应用的信息,请参阅 “同一个应用,安装前与安装后”: (https://developer.android.google.cn/topic/instant-apps/ux-best-practices.html#instant-v-installed) Q:我如何才能分辨出我的应用正在以可安装模式还是免安装模式运行? A:您可以使用静态的 InstantApps.isInstantApp ( ) 方法。如果接受测试的进程属于一个免安装应用,这个方法的返回值将为 True 。 Q:我要如何鼓励用户从免安装应用中安装我的应用? A:您可以使用静态的 InstantApps.showInstallPrompt ( ) 方法。这种方法会鼓励用户安装常规 APK 版本的应用。 Q:为各种功能使用的不同的 APK 会不会在 Google Play 里显示为不同的产品? A:不会,免安装应用与可安装应用共享相同的包装名和产品列表。 Q:我在免安装应用内为功能命名时,会不会受到限制? A:功能模块遵循 Java 命名规则。例如,您不能在功能名称中使用连字符。想要了解更多关于 Java 命名规则的内容,请参阅对应的 Java 文献: (https://docs.oracle.com/javase/tutorial/java/package/namingpkgs.html) 3. Google 分析、Google Play 与部署 Q:我能让我的免安装应用只在限定的几个国家内发布吗? A:免安装应用的使用范围限定于相应的可安装应用所在的国家和地区。在这些国家和地区的范围内,开发者可以选择在特定地区内发布自己的免安装应用。 Q:如果我想要通过 Google Play 在发布前测试我的免安装应用,我还需要首先发布可安装应用的 APK 吗? A:想要通过 Google Play 在开发阶段测试您的免安装应用的部署情况,您就必须在 Google Play Console 中拥有 “草稿” 形式的可安装版本应用。 想要了解更多关于对您的免安装应用的进行部署,以及对其部署情况进行测试的信息,请参阅上面提到的 “发布您的免安装应用”。 4. 应用大小 Q:4MB 的总下载限制是什么意思? A:免安装应用的大小(基本功能加上任何附带的附加功能)应该越小越好。您的应用越小,用户下载使用起来就越容易。但是,当您的免安装应用已经运行在用户的设备上时,您就可以使用用户的设备来下载并储存额外的数据。如果是用这种方式在用户的设备上使用数据,则不存在 4MB 的硬限制。 想要计算应用大小的话,只需解压免安装应用的 APK 并检查 APK 文件。您可以使用 APK 文件的磁盘容量,或是打开 APK Analyzer 并观察 Raw File Size 值。 对于那些拥有多个功能的免安装应用,您必须把基本功能 APK 的大小与单一功能 APK 合并计算。基本功能与单一功能 APK 文件大小之和必须小于 4MB。 Q:用户每次下载同一个免安装应用时都需要下载基本功能 APK 和附加功能 APK 吗? A:当用户首次下载免安装应用时,他们会下载基本功能和附加功能两个 APK。当用户请求其他功能的 APK 时,用户只会收到与所请求功能的 APK。在这种情况下,基本功能 APK 不需要被重复下载。 * 注意:系统会在垃圾整理期间根据需要清理免安装应用的缓存。如果手机重启,缓存会清空。如果免安装应用的缓存被清空,用户就必须重新下载基本功能的 APK。 Q:何时会触发 4MB 验证? A:当您在制作阶段将免安装应用上传到 Google Play Console 时就会触发验证。 5. 应用链接、深链接与 URL 处理 Q:用户从一些应用点击链接时,链接并没有打开我的免安装应用,而是在应用内浏览器中打开了。有没有办法能保证用户被带到免安装应用里面去? A:App Link 只是普通的 URL,所以应用可以强迫它们在应用内浏览器中打开。请考虑使用 Firebase Dynamic Links 来包装您的 URL,确保用户在点击您的链接时总能被带到您的免安装应用里去。 Q:我的主应用 manifest 里包括其他 URL 和其他 URL 域名,但我并不拥有这些域名。这样会产生什么后果? A:很遗憾,如果一个 URL 的域名所有权未经确认,则会导致免安装应用发布失败。 6. 在设备上运行免安装应用 Q:用户能否放弃使用 Android Instant App? A:能。用户在首次启动免安装应用时可以选择放弃。用户还可以选择打开 Settings 并点击 Google > Instant Apps 进行设置。 Q:两个免安装应用可以同时运行吗? A:可以。免安装应用可以同时运行,用户可以在多个应用之间切换。只有位于前台的免安装应用会在通知栏内显示图标。 Q:用户能否在 “最近使用” 栏和设备主屏上结束和重启免安装应用的进程? A:免安装应用可以从 “最近使用” 栏重启,用户还可以点击之前运行过的启动 URL 来重启应用。 当用户停止与免安装应用互动时,免安装应用的进程即被终止。但是,应用的内部存储,如 SQLite DB 还有共享偏好会保留下来。如果设备存储空间告急,免安装应用可能会被删除,它的内部存储也会一同被删除。虽然这种情况不太可能出现,但当它出现的时候还想恢复用户的使用状态和偏好信息的话,开发者需要从服务端解决。 Q:免安装应用能不能启动用户设备上安装的其他应用? A:免安装应用可以通过发出隐式意图 (implicit intent) 来启动一个可安装应用,但无法使用显式意图 (explicit intent) 来启动大多数可安装应用。但可安装应用可选择对那些发出显式意图的免安装应用开放。 Q:如果用户安装了较旧版本的应用,并点击了与较新版本免安装应用相关联的 URL,会打开哪个应用? A:可安装应用永远优先于免安装应用打开。 Q:用户如何接收我的免安装应用的最新版本? Google 会不会在用户的设备上自动对它进行更新? A:最新版本的免安装应用将提供给新用户使用,现有用户的免安装应用缓存过期时,也会获取最新版本的应用。 以上就是这一次的 FAQ 内容。想要打造良好的免安装体验,请点击“阅读原文”进一步查阅我们的最佳案例。如果您手里已经有安装版本的应用,何不试试再进一步,让您的应用无需安装即可使用呢?

优秀的个人博客,低调大师

Android官方开发文档Training系列课程中文版:Android的安全建议

原文地址:http://android.xsoftlab.net/training/articles/security-tips.html Android系统内置的安全策略可以有效的降低应用程序的安全问题。所以默认创建的应用程序已经包含了一定程度的安全保护措施。 Android所包含的安全策略有: 应用程序沙箱,它可以使APP的数据、代码与其它APP相互隔离。 应用程序框架对于常见防护措施的强大实现,比如密码、权限以及安全的IPC机制。 一些安全技术的应用,比如ASLR, NX, ProPolice, safe_iop, OpenBSD dlmalloc, OpenBSD calloc, 以及Linux mmap_min_addr,可以降低常见的内存管理错误风险。 文件加密系统可以保证设备在丢失后其中的数据不被盗取。 用户权限授予可以限制访问系统特性以及用户数据。 Android定义的权限可以控制程序的数据只能在程序的控制范围之内。 本文中所提及的Android安全策略对于日常开发非常重要,应养成良好的编码习惯。在日常的编码行为中使用以下策略可以有效降低无意中造成的安全风险。 数据存储 应用程序常见的安全问题就是它们的数据是否可被其它应用程序访问到。Android有3种基本的数据存储方式。 内部存储 默认情况下,由APP自己创建的文件只能由APP本身访问。这种防护措施由Android框架实现,也足以应对大多数应用的安全情况。 通常应当避免为IPC文件使用MODE_WORLD_WRITEABLE模式或MODE_WORLD_READABLE模式,因为这些模式没有对数据的访问提供限制能力,也没有在数据格式上做任何控制。如果需要在进程间共享数据,你应当考虑使用ContentProvider。ContentProvider对APP提供了数据读写权限,也可以按照实际情况动态的授予权限。 如果需要对一些较为敏感的数据提供额外的保护,你可以使用密钥对本地文件进行加密。比如,可以将密钥放入KeyStore,并以用户密码将其保护起来。不过这种方案也不是万能的:某些破解手段可以监视用户所输入的密码,不过这种方式可以对丢失的设备进行保护。 外部存储 在外部存储器上创建的文件可被全局读写。因为外部存储器可被用户移除,也可以被任何的应用程序修改,所以不应当在外部存储器上存储敏感的用户数据。 正因为可能存在不可信资源,所以从外部存储器中读取数据时应当执行输入验证。我们强烈的建议不要在外部存储器上存储用于动态加载的可执行文件或者类文件。如果APP需要从外部存储器上接收可执行文件,那么这些文件应当是被签过名的,在加载之前也应当对这些签名进行校验。 内容提供者 ContentProvider提供了一种结构化的存储机制,这种机制可以对所有的应用程序形成一种约束。如果不打算使其它的应用程序访问你的ContentProvider,那么只需在程序的清单文件中标记ContentProvider的属性android:exported=false即可。否则,设置android:exported=true便意味着其它应用程序可以访问其中的数据。 在创建ContentProvider时默认允许其它应用程序可以访问其中的数据,你可以对读或者写进行单一权限限制,也可以同时管理。 如果使用ContentProvider只是为了在自身的APP之间共享数据,更加合理的方式是将android:protectionLevel属性值设置为”signature”。Signature权限不需要用户确认,所以这样可以提供良好的用户体验,以及更多的控制力。 ContentProvider还可以通过android:grantUriPermissions属性提供更细粒度的访问能力。访问者应当在Intent中使用FLAG_GRANT_READ_URI_PERMISSION标志或FLAG_GRANT_WRITE_URI_PERMISSION标志进行访问。这些权限的范围可被做更进一步的限制。 当访问ContentProvider时,使用参数化方法比如query(), update(), 及delete()可以避免不可信来源的SQL注入。 不要对写入权限的安全拥有错误的认知。考虑一下,写入权限允许执行SQL语句,这可能会使一些数据被确认。比如,一名攻击者可能会在通话记录中查找一个指定的电话号码是否存在,如果这条数据存在,那么攻击者只需进行修改便可得知结果。如果ContentProvider的数据结构可被猜测出,那么写入权限就相当于也同时提供了读取权限。 使用权限 因为Android每个应用都处于沙箱之内,所以如果需要共享资源与数据的话,应用必须显式的声明自有权限。 请求权限 我们推荐应用程序所需的权限越少越好。这样可以降低权限滥用的风险,也更易让用户接受,也可以减少黑客的攻击入口。通常情况下,如果某个权限不是必要的,那就不要去请求它。 如果应用程序可以做到不需要任何权限,那么这是最完美的。比如,如果需要通过访问设备信息的方式来创建唯一标识符的话,我们更推荐GUID。又比如,相比于将数据存储于外部存储器,我们更推荐内部存储器。 另外在请求权限时,可以使用< permissions>来保护IPC。IPC对于安全特别敏感、薄弱,并且它会被暴露给其它应用程序,比如ContentProvider。 除了可能需要用户确认的权限之外,我们更推荐使用访问控制,因为这些权限可能会使用户感到困惑、不解。比如,可以考虑对个人开发者的应用程序使用”signature“的IPC权限保护等级。 不要泄露受保护的权限数据。这种情况仅会发生在通过IPC共享数据时:因为它拥有特殊的权限,并且对于任何的IPC接口的客户端也没有要求出示该权限。 More details on the potential impacts, and frequency of this type of problem is provided in this research paper published at USENIX:http://www.cs.berkeley.edu/~afelt/felt_usenixsec2011.pdf 创建权限 通常情况下应当尽量少的使用权限,少用权限就意味着更安全。创建权限这种事情对于大多数应用来说是用不到的,因为系统定义的权限足以涵盖所有情况,这些权限会提供访问检查。 如果必须创建权限,考虑是否可以使用”signature”保护等级完成你的所需任务。”signature”会将自身完全暴露给用户,只允许具有相同签名的应用程序访问。 如果要创建”dangerous”保护等级的权限,那么有些东西需要考虑在内: 权限必须提供一段简短的描述该权限安全的字符串。 描述权限的字符串必须提供不同地区的语言。 如果权限的描述含糊不清或者用户认为这会为其带来风险,那么用户可能会选择不安装应用。 如果权限的生成器没有安装的话,应用程序可能会请求权限。 上面的每一条对于作为程序员的你都是一项重要的非技术性挑战,这样做可能会使用户感到困惑,这就是为什么我们不鼓励使用”dangerous”权限等级的原因。 网络安全 网络传输本身就存在安全风险,因为它会包括用户的隐私数据。人们越来越关心移动设备的隐私问题,尤其是执行网络传输时,所以APP需要至始至终以最佳的安全方案保护用户的数据安全。 使用IP网络 Android所处的网络环境与其它的Linux系统有着很大的不同。主要考虑的就是选用适用于敏感数据传输的协议。比如HttpsURLConnection用于安全的WEB通信。我们推荐在支持HTTPS,因为移动设备会频繁的连接到不可信网络,比如公共的Wi-Fi热点。 经认证,Socket等级的加密通讯可以使用SSLSocket类简单实现。鉴于Android设备会频繁的连接到不安全的无线网络,所以我们强力的建议对所有的应用程序都使用安全的网络实现。 我们也见过一些应用在处理敏感的IPC上使用了localhost网络端口。我们不鼓励使用这种方式,因为这些接口能被其它应用程序访问到,应当使用Android的IPC机制。 还有一个常见的问题就是,根证书重复用于验证从HTTP或者其它网络上下载的不可信数据。这也包括WebView以及HTTP请求响应的输入验证。 使用电话网络 SMS(短消息服务)协议主要用于个人对个人之间的通讯,它并不适用于APP的数据传输。由于SMS的限制,我们强烈的推荐使用Google Cloud Messaging(GCM)及IP网络来传输服务器与设备之间的数据。 要注意,SMS既没有对网络和设备进行加密也没有对其进行相关验证。尤其是,任何的SMS接收器应当考虑到会有一位恶意的用户会发送SMS给你的应用,不要相信没有验证过的SMS数据,并用它们来执行一些敏感操作。还有,你应当意识到SMS可能会在网络上被拦截并被篡改。在Android设备内,SMS消息是由广播意图传送的,所以这些数据可以被拥有READ_SMS权限的应用程序读取到。 输入验证 无论程序运行在哪个平台上,没有执行充分的输入验证都是影响程序安全的主要原因之一。Android提供了平台等级的安全策略,这可以降低应用程序输入验证问题的暴露率,应用程序应当尽可能的使用这些平台特性。还应该注意:安全性语言的选择倾向于减少输入验证问题的可能性。 如果你在使用本地代码,那么从文件中读取的数据、从网络上接收的数据或从IPC接收的数据都可能会引起安全问题。最常见的问题就是缓冲区溢出,使用释放后的对象等等。Android提供了大量的相关技术手段比如ASLR(Address Space Layout Randomization)、DEP(Data Execution Prevention),这些技术手段可以降低这些错误的出现频率,但是它们不会解决根本的内在问题。你可以谨慎的处理指针或管理缓冲区来防止这些问题的出现。 如果使用SQL数据库或者ContentProvider进行数据查询,那么SQL注入可能是个问题。避免这些问题最好使用参数化的查询方法。将权限降为只读或只写可以降低SQL注入带来的相关风险。 如果不能够使用以上提及的安全建议,那么我们强烈推荐使用结构良好的数据格式,并在使用时对这些数据格式进行验证。 处理用户数据 通常来说,对于用户的数据安全最好的方法就是尽量少使用可以访问到敏感数据或者用户数据的API。如果可以避免存储或者传输这些信息,那么就不要传输这些数据。可考虑应用程序是否能够实现这么一种逻辑:使用数据的哈希码或者一种不可逆的数据形态。比如,程序可能会实现这么一种逻辑:将电子邮件地址的哈希码作为一个关键的值,这样可以避免使用原有的电子邮件地址,这可以降低暴露数据的机会,也可以降低攻击者入侵应用程序的机会。 如果程序需要访问用户的个人信息,比如密码或者用户名等等,要记住一些组件可能会要求你提供相关的隐私政策,来解释这些数据的使用与存储。所以接下来数据访问实践可以简化遵循规则。 你还应当考虑应用程序是否有无意中将用户的个人数据暴露给了第三方。如果你不清楚这些第三方组件或服务为什么要使用用户的信息,那么就不要提供给它们。通常降低个人信息的访问可以降低这块的安全风险。 如果必须要访问敏感数据,那么评估一下这些信息是否有必要传输到服务器,或者是否这些操作只需在客户端执行就可以。考虑凡是涉及到用户敏感数据的代码都在客户端执行,这样可以避免不必要的网络传输和安全泄漏问题。 还有,要确保没有将用户数据通过IPC、全局可读写文件或者网络Socket暴露给其它应用程序。 如果需要GUID,可以创建一个大的唯一的数据将其保存下来。不要使用与电话有关的数字,比如电话号码、IMEI,这些信息可能会与用户信息有关。 写入设备日志时要当心。在Android中,日志是共享资源,可被具有READ_LOGS权限的应用读取到。尽管日志数据是临时的,但是不恰当的用户信息日志可能会无意中将信息泄露给其它应用程序。 WebView的使用 因为WebView会解析像HTML和JavaScript这样的web内容,所以不正确的使用会带来常见的安全隐患。Android提供了大量机制来收缩这些潜在问题的范围,比如通过限制WebView的能力来达到最低的运行需求。 如果程序没有直接使用到WebView中的JavaScript,那么不要调用setJavaScriptEnabled()。一些示例代码可能会使用该方法,所以如果不需要的话,在你的程序中关闭它。默认情况下,WebView不会执行JavaScript,所以不会发生跨站脚本攻击。 使用addJavaScriptInterface()需要特别当心,因为它会允许JavaScript调用预留给Android原生应用的方法。如果你使用它,要确认所有的Web的相关内容都是可信的。如果不可信的内容允许进入,那么不可信的 JavaScript 可能会调用App内的相关方法。一般我们推荐在APK内包含JavaScript代码的时候使用addJavaScriptInterface()。 如果程序通过WebView访问敏感数据,你可能需要使用clearCache()方法来删除存储在本地的所有文件。我们可以使用HTTP头部的某些属性比如no-cache来表示应用程序不应当缓存某些特殊的内容。 Android 4.4之前版本的webkit含有大量的安全问题。如果App运行在这些版本上,应当确认WebView所渲染的内容都是可信的。如果应用必须渲染开放的Web内容,考虑实现一个独有的渲染器,这样可以及时更新相关的安全补丁。 管理证书 通常来说,我们不推荐频繁的要求用户凭证,推荐使用授权令牌。 用户名及密码通常不应该存在本地。应当使用用户输入的用户名及密码进行初始化验证,然后使用一个权限Token进行通信。 如果一个账户需要被多个程序访问,那么应当使用AccountManager。如果可能的话,使用AccountManager与服务进行交互,绝不要将密码存在设备上。 如果证书只是用作于你创建的应用程序,那么可以使用checkSignature()方法进行程序访问验证。如果只有一个程序使用了证书,那么KeyStore可能更适合你。 使用密码 除了数据隔离、文件系统加密、安全通信通道等保护手段之外,Android还提供了一系列通过算法加密的安全保护措施。 通常情况下,Android内置的最高等级的安全实现已经可以支持各种安全情况。如果需要从一个已知的位置接受一个文件,那么HTTPS URI已经足够。如果需要一条安全通道,考虑使用HttpsURLConnection或SSLSocket。 如果发现确实需要实现自己的安全协议,不建议自己实现加密算法。而应当使用已有的加密算法比如在Cipher中提供的AES加密算法或RSA加密算法。 使用安全随机数生成器SecureRandom来初始化密钥KeyGenerator。如果不使用由SecureRandom生成的密钥的话,则会大大减弱加密算法的健壮性,也更容易遭受线下攻击。 如果需要将密钥存在本地以便后续使用,那么可以使用KeyStore类似的加密机制。 使用进程间通信 一些App尝试使用传统的Linux技术比如网络Socket和共享文件来实现IPC。我们对此推荐使用Android为IPC实现的系统功能,例如Intent,Binder,Messenger和BroadcastReceiver。Android的IPC机制允许验证连接到你IPC的程序的身份,并且可以对每个IPC机制设置安全策略。 许多安全元素通过IPC机制共享。如果你的IPC机制的目的不是为了供其他应用程序使用,那么请将对应元素的android:exported的属性设置为false。这对于由相同UID的多进程组成的应用很有帮助,或者对后期再开启该功能也有一定的帮助。 如果IPC的目的是为了可被其他应用访问,你可以通过使用< permission>元素指定安全策略。如果IPC只是为了在持有相同key的两个自有应用中使用,那么android:protectionLevel=”signature”则更为适合。 使用Intent Intent是异步IPC的首选机制。这取决于程序的需求,你可能会使用sendBroadcast(), sendOrderedBroadcast()或者显式Intent来指定应用程序组件。 要注意,由于有序广播可以被接收方消耗掉,所以这些广播可能不会被分发给所有的应用程序。如果你发送了一个广播,而该广播必须被指定接收器接收的,那么必须使用显式Intent,并且该Intent还需指明广播接收器的名称。 发送Intent的一方可以验证接收方是否允许非空的权限方法调用。只有含有该权限的应用才会接收到该Inetnt。如果广播中的Intent的数据是敏感的,那么应当考虑这里所使用的权限不会被非法的应用程序拦截。在这种情况下,你应当考虑直接调用接收器,而不是使用广播。 **Note:**Intent filters不应当被视作为一种安全特性:因为组件可能会由显式的Intent调起。你应当在收到Intent的地方执行输入验证来确认该Intent是否被格式化为适用于调用广播接收器,服务或者Activity的格式。 使用服务 Service经常被用作支持其他程序的功能。每个Service必须在它的清单文件中有相应的声明。 默认情况下,Service不是开放的,也不能够被其它应用程序调起。然而,如果在Service的声明中添加了IntentFilter,那么默认就会被暴露出去。最好的办法就是显式的声明android:exported属性为你需要的属性。Service还可以由android:permission属性保护。如果这么做了,那么其它的程序则需要在它们的清单文件中声明对应的权限才可以启动、停止或者绑定该服务。 Service还可以保护在其权限内的IPC调用,在执行这个调用的实现之前调用checkCallingPermission()进行必要检查。我们通常推荐使用在清单文件中声明的权限,因为有很多漏洞会被忽略。 使用Binder及Messenger接口 Binder、Messenger是远程过程调用的首要IPC机制。它们提供了一种定义良好的接口:可以进行端对端相互认证。 我们强烈推荐以不需要特定的权限检查的方式设计接口。由于Binder、Messenger并不是在应用的清单文件中声明过的,因此不能对其采用特定权限。它们的权限通常来自于对应的Service或Activity所声明的权限。如果你创建了一个用于请求验证或者访问控制器的接口,那么这些控制器必须显式的添加在Binder、Messenger的接口中。 如果创建了一个需要访问控制器的接口,使用checkCallingPermission()验证调用者是否含有所需的权限。这在访问服务的远端代理之前尤其重要,正如你的应用的身份需要传给其它接口一样。如果调用一个由Service提供的接口,那么如果你没有访问给定服务所需的权限,那么bindService()的调用可能会失败。如果调用一个由自身APP提供的一个本地的接口,那么clearCallingIdentity()则可以满足内部安全检查的需求。 有关更多执行与服务有关的IPC的相关信息,请参见Bound Services。 使用广播接收器 BroadcastReceiver用于处理由Intent发起的异步请求。 默认情况下,接收器可以被任何应用调起。如果你的广播接收器的作用是给其它程序使用,那么可能需要对接收器采取一些安全措施:在清单文件中添加相应的安全权限。这可以防止没有正确权限的应用程序发送Intent给广播接收器。 动态加载代码 Dalvik是Android的运行时虚拟机。虽然Dalvik专用于Android,但是其它虚拟机上的相关安全问题也同样适用于Android。一般不需要关心与虚拟机相关的安全问题,因为Android的应用程序运行在安全的沙箱环境中,所以系统上的其它进程访问不到程序的代码或者私有数据。 如果你对更深的虚拟机安全课题感兴趣,那么推荐熟悉一些现有的有关这一课题的相关文献。其中最受欢迎的两个资源如下: - http://www.securingjava.com/toc.html - https://www.owasp.org/index.php/Java_Security_Resources 这篇文档主要关注于Android的特殊之处和与其它虚拟机环境有什么不同。对于对其它虚拟机很有经验的开发者来说,这里有两个很主要的Android的不同之处: 一些虚拟机,比如JVM或.net运行时,扮演了一个安全边界的角色,从底层操作系统将代码、功能隔离。然而在Android中Dalvik虚拟机并没有这样的功能——应用程序沙箱实现与操作系统层面,所以Dalvik可以与应用的本地代码进行交互,而没有任何的安全限制。 由于移动设备有限的存储空间,一些开发者可能需要通过模块化构建应用程序,并使用动态加载技术。如果这么做,那么则需要考虑在哪接收应用的逻辑代码?又应当将这些代码存在哪?不要使用没有经过验证的代码,比如从不安全的网络资源上或者是外部存储器中加载的代码,因为这些代码很有可能会被其它程序篡改。 本地代码的安全 一般我们推荐使用Android SDK来进行应用程序开发,而不是使用本地代码开发。由本地代码构建的程序会更加复杂,也缺少了灵活性,也更容易产生像缓冲区溢出等常见的内存泄露错误。 因为Android建立于Linux kernel基础之上,所以如果使用本地代码的话,那么Linux开发中所遇到的安全问题也同样适用于此。由于Linux安全相关超出了本文的范围,所以这里提供了很受欢迎的“Linux和Unix如何安全编程”的相关资源,相关地址:http://www.dwheeler.com/secure-programs. Android与其它大部分Linux环境最大的不同就在于程序沙箱。在Android中,所有的程序都运行在程序沙箱中,也包括那些本地代码。在最基本的层面上,对熟悉Linux的开发者来说,不同之处就是Android的每个应用程序都有一个唯一UID,也拥有少量的权限。如果要使用本地代码开发的话,那么应当对应用的权限极为了解才对。 PS: 翻译的相关源文件皆已开源,开源地址:https://code.csdn.net/u011064099/android-training-chinese-version/tree/master,欢迎fork、star。

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册