原文:http://android.eoe.cn/topic/summary
Android 4.1 (Jelly Bean)发布了,这次发布包含了一些性能及用户体验上面的优化。也为用户和开发人员添加了一些新的功能。本文主要介绍了一些对于开发人员来说比较关注或者说有用的api。
对于应用开发人员来说,Android 4.1里面包括了SDK编译包(可以编译你应用程序用于在android 4.1平台上面运行),和一个可以在模拟器中运行的系统镜像。开发人员应该尽快下载SDK编译包及系统镜像,并且在Android 4.1平台上面编译与测试你的应用程序。如果想在Android 4.1平台上面从事开发和测试工作,请使用Android SDK Manager来下载相关的最新内容。
通过指定的[http://developer.android.com/guide/topics/manifest/service-element.html#isolatedandroid:isolatedProcess=true]中的"<service>标签,您的Service将在没有自身权限的被隔离的用户ID进程下运行。
新的ComponentCallbacks2常数,例如TRIM_MEMORY_RUNNING_LOW和TRIM_MEMORY_RUNNING_CRITICAL在系统调用onLowMemory())方法之前就提供前台进程的内存状态。
新的getMyMemoryState(ActivityManager.RunningAppProcessInfo))方法允许您直接查询一般的内存状态。
一个新的方法,acquireUnstableContentProviderClient())允许您可能以一种“不稳定”的方式访问ContentProviderClient以至于如果这个content provider在工作,你的应用就不会崩溃。当你在用content provider在一个单独应用交互的时候这个方法很有用。
新的intent协议直接启动动态壁纸预览的activity来帮助用户在不需要强迫离开您的程序就能简单地选择动态壁纸并且通过手机壁纸选择器进行导航。
为了启动这个动态壁纸选择器,通过一个使用ACTION_CHANGE_LIVE_WALLPAPER的intent和额外的一个以EXTRA_LIVE_WALLPAPER_COMPONENT作为您指定的动态壁纸ComponentName的一个字符串来调用[startActivity()]方法
Android4.1采用了更容易的实现向上导航的设计模式。你所需要做的就是在你的manifest文件之中把android:parentActivityName增加到每个元素中去。这个系统通过该信息在当用户按操作栏中向上按钮(同时也完成当时的activity)来打开相应的活动。所以如果您为每一个activity都声明了android:parentActivityName,您就不需要用onOptionsItemSelected())这个方法处理点击操作栏的应用程序事件图标————现在的系统处理这一事件,并恢复或建立适当的活动。
在某些特定情况之下,当用户通过一个“深潜”的intent进入你到您应用中的某一个activity就好像从其它应用程序的一个通知或者意图中进入(就如设计指南中描述应用程序之间的导航那样)。当用户以这样的方式进入您的activity,您的程序也许会有不自然的回栈的activity可以用来恢复用户导航。然而,当您为您的activities提供android:parentActivityName这个属性,系统会识别您的程序是否包含了返回堆栈的父类activities,如果没有,系统将会为您的程序构建一个人工合成的返回堆栈包含所有的父类activities。
注意:当用户进入您应用中的一个深度的activity时并且在您的应用程序中创建一个新的任务,系统实际上是将父类activities的的堆栈插入到这个任务中。正因为如此,按下“Back”按钮也从父类的activities堆栈中导航返回。
当系统为您的应用程序创建一个合成的回栈,它也有个基本的Intent来为每一个父类activity来创建一个新的实例。所以它没有像你期望的那种以用户自然的通过每一个activity来进行导航的方式为父类的activities保存状态。如果任何的父类activities通常显示一个依赖于用户将要丢失的上下文的界面,那么您应该在用户从堆栈中导航返回的时候记录下来。例如,如果一个用户正在一个音乐的应用中浏览一个专辑,导航也许会为带他进入到一个列选选定的音乐流派的所有专辑的activity。在这种情况之下,如果必须创建堆栈,您很有必要通知这个父类的activity当前的这个专辑属于什么流派,以此来让这个activity显示正确的列表就好像用户确实是从原来那个activity过来的一样。为了在一个合成的父类的activity中实现这些信息,您必须重写这个onPrepareNavigateUpTaskStack())方法。该方法为您提供了一个TaskStackBuilder对象以供系统创建来合成父类的activities。这个TaskStackBuilder对象包含系统用来创建每个父类的activity的Intent对象。在您实现
onPrepareNavigateUpTaskStack())的方法的时候,你可以修改对应的Intent来增加额外的数据使父类activity能够用来决定对应的上下文和显示相应的界面。
当系统创建了这个TaskStackBuilder类之后,它会增加用来创建那些在他们逻辑顺序从activity树顶端开始的父类activities的Intent对象。因此,最后添加到内部数组的的Intent就是当前活动的直接父类。如果你想为这个activity的父类修改这个Intent,首先要通过[http://developer.android.com/reference/android/app/TaskStackBuilder.html#getIntentCountgetIntentCount]方法来确定这个数组的长度并且将值放在[http://developer.android.com/reference/android/app/TaskStackBuilder.html#editIntentAt(int)editIntentAt]方法之中。()
如果您的应用程序结构比较复杂,还有一些其他可用的APIs来帮助你处理向上导航的行为以及完全定制合成的回栈。这些APIs中的一部分还给你一些额外的控制包括:
onNavigateUp())
重写这个方法是为了当用户按下“UP”按钮时定义一些自定义的操作。
[http://developer.android.com/reference/android/app/Activity.html#navigateUpToandroid.content.Intent)navigateUpToIntent)(]
调用该方法是为了结束当前的activity并且跳到根据提供的Intent所显示的那个activity上去。如果这个activity在回栈中存在,但是不是最近的一个父类,那么所有在当前activity和指定activity之间的其它的activities也全部结束。
[http://developer.android.com/reference/android/app/Activity.html#getParentActivityIntentgetParentActivityIntent()]
调用这个方法类获得启动在逻辑上是当前activity的父类的Intent。
shouldUpRecreateTask(Intent))
调用此方法是用来查询一个合层的回栈是否必须为了导航来创建。如果一个合成的栈需要被创建就返回true,如果该堆栈存在就返回false。
finishAffinity())
调用该方法是为了结束当前的activity和所有与当前activity有相同任务关系的所有父类activities。如果你重写了默认的行为例如onNavigateUp()),你应该在你创建一个基于向上导航合成的回栈使用该方法。
onCreateNavigateUpTaskStack)
如果你需要完全控制合成任务堆栈的创建的所有过程,就重写该方法。如果你只是想简单添加一些数据到你回栈的intent中去,你就应该重写onPrepareNavigateUpTaskStack())这个方法。
然而,大部分的应用程序都不需要使用这些APIs或者实现onPrepareNavigateUpTaskStack())方法,但是可以达这个到正确的行为仅仅通过为每一个元素添加android:parentActivityName就行了。
MediaCodec类是用来为低级别的媒体编码和解码的媒体编解码器提供访问。您可以实例化一个MediaCodec类通过调用createEncoderByType())方法来进行对媒体文件进行编码或者调用[http://developer.android.com/reference/android/media/MediaCodec.html#createDecoderByTypejava.lang.String)createDecoderByType)]来对媒体文件进行解码。每一个方法都要采取一个MIME类型为你想要编码或者解码的媒体文件类型,例如“video/3gpp”或者“audio/vorbis”。(
在MediaCodec实例创建之后,你可以调用android.view.Surface, android.media.MediaCrypto, int) configure()方法来指定例如媒体格式或者是否对内容加密的属性。
无论你是对你的媒体文件进行编码还是解码,在你创建MediaCodec实例后的其余进程都是一样的。首先通过getInputBuffers())的方法获得输入ByteBuffer对象的一个数组然后再通过getOutputBuffers())方法来获得一个输出的ByteBuffer的对象数组。
当你准备好进行编码或者解码的时候,调用dequeueInputBuffer())方法来获得这个用来作为媒体文件源码的ByteBuffer(从输入的buffers的数组中)的索引位置。在你使用带有媒体文件源码的ByteBuffer之后,通过调用int, int, long, int)queueInputBuffer()方法来释放缓存区的所有权。
对输出缓存区也是一样的,调用long) dequeueOutputBuffer()方法来获得你接收到结果的ByteBuffer的索引位置。在你从ByteBuffer读出输出之后,通过调用boolean)releaseOutputBuffer()方法来释放所有权。
你可以结合MediaCrypto APIs,而不是正常的int, android.media.MediaCodec.CryptoInfo, long, int) queueInputBuffer()方法,通过调用int, int, long, int)queueSecureInputBuffer()的方法来处理媒体媒体编解码器的加密数据。
想要了解更多关于如何使用编解码器的信息,参见MediaCodec文档。
新方法startRecording())允许你可以在MediaSyncEvent的定义提示下的基础上开始录音。这个MediaSyncEvent指定一个当完成时就能自发触动录音机开始录音的音频对话(例如一个被MediaPlayer所定义的对话)。例如,您可以使用这个功能播放提示音来表示一段录音会话的开始,然后这个录音就自动开始,所以你没不必手动同步提示音和录音开始的操作。
MediaPlayer这个类现在可以处理带内和带外的文本轨道。带内文本轨道就是一个MP4或3GPP的媒体源的文本轨道。带外文本轨道可以通过addTimedTextSource()这个方法来本当作一个外部的文本进行添加。在所有的外部文本轨道添加之后,调用android.net.Uri, java.lang.String)getTrackInfo()方法来对数据源中所有的可用的轨迹的列表进行刷新。
如果要用MediaPlayer这个类来设置轨道,你必须调用selectTrack())这个方法选择你想要设置的轨道的索引位置。
当得知到这个文本轨道准备开始时,实现MediaPlayer.OnTimedTextListener这个接口并且把它传到setOnTimedTextListener())方法中去。
AudioEffect这个类现在支持当捕获到音频时额外的的音频预处理类型:
作为声学回声消除器(AEC)的AcousticEchoCanceler这个类消除了从远程捕捉到音频信号上的信号的作用。
作为自动增益控制(AGC)的AutomaticGainControl这个类自动恢复正常捕获的信号输出。
作为噪声抑制器的(NS)的NoiseSuppressor这个类可以消除被捕获信号的背景噪音。
您可以应用这些利用AudioEffect一个子类的AudioRecord类上的音频捕获预处理效果。
注意:并不能保证所有的设备都能支持这些效果的,所以你应该首先调用在对应音频效果类上的[http://developer.android.com/reference/android/media/audiofx/AcousticEchoCanceler.html#isAvailableisAvailable]的方法来检测它的可用性。()
现在您可以在两个完全独立的MediaPlayer类上执行无缝播放。在您第一个MediaPlayer类执行结束前的任何时间调用setNextMediaPlayer())这个方法,然后Android系统将会在您第一个停止的时候紧接着播放第二个文件。
媒体路由器。这个新的APIs MediaRouter,MediaRouteActionProvider和MediaRouteButton为您在播放文件的地方提供标准的机制和界面供您选择。
新增接口Camera.AutoFocusMoveCallback,允许你监听自动对焦动作。你可以使用setAutoFocusMoveCallback())注册你的接口。之后,当照相机处于持续自动对焦模式下(FOCUS_MODE_CONTINUOUS_VIDEO或者FOCUS_MODE_CONTINUOUS_PICTURE),你会收到一个android.hardware.Camera) onAutoFocusMoving()的回调。这个回调方法告诉你自动对焦是否已经开始移动或者已经停止。
MediaActionSound类提供了一个简单的API集,用于发出由相机或者其他媒体创建的声音。当拍照或者摄像的时候,你应当使用这些API播放适当的声音。
当播放声音时,只要使用一个MediaActionSound对象,调用load())预加载需要的音频,然后在适当的时间调用play())即可。
Android Beam™ 现在支持蓝牙设备上的大数据量传输。当你使用新的[http://developer.android.com/reference/android/nfc/NfcAdapter.html#setBeamPushUrisandroid.net.Uri[](, android.app.Activity) setBeamPushUris()]方法或者新的回调接口NfcAdapter.CreateBeamUrisCallback定义待传输的数据,Android会关闭蓝牙或者另一个交互传输系统的数据传输,以取得更高的传输速度。这对大数据量特别有效,比如图像和影像文件,并且不需要在设备间进行显式的配对。这不需要你的应用来做更多的工作就能够发挥蓝牙传输的优势。
[http://developer.android.com/reference/android/nfc/NfcAdapter.html#setBeamPushUrisandroid.net.Uri[](, android.app.Activity) setBeamPushUris()]方法用一个Uri对象的数组以指定在应用中想要传输的数据。另外,你也可以实现NfcAdapter.CreateBeamUrisCallback接口。这样,你就能够通过调用android.app.Activity) setBeamPushUrisCallback()方法为你的activity指定数据。
当使用这个回调接口时,用户每次使用Android Beam执行了一次共享,系统会调用接口的createBeamUris())方法以便于你能够定义需要共享的URI。对于待分享的URI会随着activity中的用户环境变化而变化的情况下,这是有用的。反之,如果待分享的URI不会改变,那么你可以安全地使用setBeamPushUris())方法提前定义它们。
Android 4.1添加了基于DNS的多播服务发现的支持。通过Wi-Fi,它允许你发现并连接对应的设备提供的服务。这些设备包括可移动设备、打印机、照相机、媒体播放器和其他注册于本地网络的设备。
新的包android.net.nsd包含了新的API。它们允许你在本地网络中广播你的服务,发现设备以及连接设备。
为了注册你的服务,首先你必须创建一个NsdServiceInfo对象,并定义服务的各种属性。需要用到的方法有setServiceName()), setServiceType())和setPort())。
然后你需要实现接口NsdManager.RegistrationListener,并使用你的NsdServiceInfo把它传给registerService())。
为了发现网络中的服务,需要实现接口NsdManager.DiscoveryListener,并传给discoverServices())。
当你的NsdManager.DiscoveryListener接收到发现服务的回调时,你需要通过调用android.net.nsd.NsdManager.ResolveListener) resolveService()解析服务。调用时,传递一个NsdManager.ResolveListener的实现(这个实现接收包含已发现服务的信息的一个NsdServiceInfo)。调用这个方法允许你初始化连接。
Wi-Fi Direct API在Android 4.1中被增强以支持在WifiP2pManager中的预先关联服务发现。这允许在连接之前使用Wi-Fi Direct通过服务发现和筛选周围的设备。与此同时,Network Service Discovery允许你在一个已存在并保持连接的网络上发现一个服务(例如一个本地的Wi-Fi网络)。
为了广播你的应用作为一个Wi-Fi上的服务,以便于其他设备能够发现并连接你的应用,需要调用addLocalService())方法并传输一个[http://developer.android.com/reference/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.htmlWifiP2pServiceInfo]对象。这个对象描述了你的应用服务。
为了通过Wi-Fi开始发现附近的设备,首先你应当决定使用Bonjour还是Upnp实现通信。如果使用Bonjour,首先要用setDnsSdResponseListeners())设置好一些回调监听器。这个方法需要WifiP2pManager.DnsSdServiceResponseListener和[http://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager.DnsSdTxtRecordListener.htmlWifiP2pManager.DnsSdTxtRecordListenerUpnp,则要调用[setUpnpServiceResponseListener()](http://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager.html#setUpnpServiceResponseListener(android.net.wifi.p2p.WifiP2pManager.Channel,%20android.net.wifi.p2p.WifiP2pManager.UpnpServiceResponseListener))。这个方法需要一个[http://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager.UpnpServiceResponseListener.htmlWifiP2pManager.UpnpServiceResponseListener]作为参数。]两个作参数。如果使用
在你开始发现本地设备上的服务之前,你也需要调用[http://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager.html#addServiceRequestandroid.net.wifi.p2p.WifiP2pManager.Channel,%20android.net.wifi.p2p.nsd.WifiP2pServiceRequest,%20android.net.wifi.p2p.WifiP2pManager.ActionListener)addServiceRequest)]方法。当你传递给这个方法的接口[http://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager.ActionListener.htmlWifiP2pManager.ActionListener]收到一个成功的回调,接着你可以通过调用[http://developer.android.com/reference/android/net/wifi/p2p/WifiP2pManager.html#discoverServicesandroid.net.wifi.p2p.WifiP2pManager.Channel,%20android.net.wifi.p2p.WifiP2pManager.ActionListener)discoverServices)]开始探索在本地设备上的服务。(
当本地服务被发现,你会收到一个回调,来自WifiP2pManager.DnsSdServiceResponseListener或者WifiP2pManager.UpnpServiceResponseListener,这个取决于你注册使用的是Bonjour还是Upnp。收到的回调都会包含一个WifiP2pDevice对象,代表了对应的设备。
新的方法isActiveNetworkMetered())允许你检查设备当前是否正确连接到metered网络。在执行网络事务之前,检查这个状态,可以帮助你管理数据的使用(那可能会消耗你的用户的金钱)以及帮助你对是否立即执行事务做出更好的决定(例如当设备将要连接到Wi-Fi的时候)。
在Android 4.1中,可访问性服务API被大大增强了。它允许你构建服务,该服务可以监视并回应更多输入事件,比如复杂的手势使用onGesture())、其他的输入事件通过添加AccessibilityEvent, AccessibilityNodeInfoand AccessibilityRecord类来实现.
可访问性服务可以模拟用户来执行一些操作,比如点击、滚动和通过使用performAction)和setMovementGranularities)来实现文本的滚动。performGlobalAction())也允许服务模拟其他的操作,比如返回、回到主屏幕、打开最进访问的应用列表和通知栏等。
当编译一个Android应用程序时,通过找到焦点元素和输入控件来自定义导航方案,需要用到findFocus())和focusSearch())方法,设置焦点需要使用setAccessibilityFocused())方法。
新的android.view.accessibility.AccessibilityNodeProvider
类利用可访问性服务允许你对复杂的自定义界面做处理,所以可以以更方便的方式呈现信息。android.view.accessibility.AccessibilityNodeProvider
类允许一个具有先进的内容的widget(比如一个日历网格)利用独立完成的布局结构去展示一个复杂语义结构。这个语义结构允许可访问性服务为在同一时刻的用户展示一个更有用的互动模型。
你现在可以使用setClipData()方法把一个ClipData对象关联到一个Intent上。当你使用一个Intent传输复杂content:URI到另一个应用程序时,这非常有用。例如当需要共享复杂文档时。以content:URI这种形式给出的URI也遵循Intent的标记,提供读写的访问权限,允许你在这个Intent中授予对复杂URI的访问权限。当启动一个ACTION_SEND或者ACTION_SEND_MULTIPLE的Intent,在Intent给出的URI会自动复制到ClipData,以便于接受者可以有权限访问它们。
ClipData类现在能够支持包含样式的文本(包括HTML和Android样式的字符串)。你可以调用java.lang.CharSequence, java.lang.String) newHtmlText()方法添加HTML样式本文到ClipData类。
Renderscript计算功能增加了以下特性:
一个脚本支持多个核心程序
支持使用通过新的API rsSample脚本计算得到的过滤采样器的分配阅读。
在#pragma支持使用不同版本精度的FP。
通过一个计算脚本,允许从RS对象请求附加信息。
多个性能提升。
新的编译注解还可用来定义计算Renderscripts时所要求的浮点型精度。这个允许你使用NEON进行运算,如在CPU路径上的快速向量数学运算,但这个在完整的IEEE 754-2008标准中是不可能的实现的。
你现在可以使用缩放动画或你自己定义的动画来启动一个活动-Activity。指定一个你想要的动画,可以使用ActivityOptions APIs来建立一个Bundle,然后你可以把它传递给任何一个用来启动一个活动的方法,如startActivity())
ActivityOptions类为你想要展示并打开的活动的每一种类型的动画都准备了一个不同的方法。
makeScaleUpAnimation())
:创建一个动画,能够从屏幕指定的位置和指定的大小拉伸一个活动窗口。例如,当打开一个应用时,Android 4.1的主屏幕使用了这个方法。
makeThumbnailScaleUpAnimation())
:创建一个动画,能够从屏幕指定的位置和提供的缩略图拉伸一个活动窗口。例如,在Android 4.1的最近使用程序窗口中,当往回一个应用程序时使用了这个动画。
makeCustomAnimation())
:创建一个动画,由你自己的资源所定义:一个用来定义活动开启的动画,一个用来定义活动被关闭的动画。
新的TimeAnimator提供了一个简单的回调机制,通过TimeAnimator.TimeListener,在动画的每一帧处通知你。这个动画器没有时间,插值或是对象值设定。回调监听器为每一帧动画接受信息,包括总运行时间和从前一帧到现在的运行时间。
在Android 4.1中,你可以创建通知栏,使用更大的内容区域,大图标预览,多动作按钮,和可配置的优先级。
新的方法setStyle()),允许你为你的通知设定三个新的样式,每一个都提供了一个更大的内容区域。为更大的内容区域指定一个样式,将setStyle()) 传递给以后的对象之一:
Notification.BigPictureStyle
:用作包含了一个大图标附近的通知。
Notification.BigTextStyle
:用作包含了很多文本的通知,例如一封邮件。
Notification.InboxStyle
:用作包含了一个字符串列表的通知,例如来自多封邮件的片断。
现在在通知消息底部支持显示两个动作按钮,不管你的通知使用的是普通或是更大的样式。
添加一个动作按钮,调用addAction())方法。这个方法使用了两个参数,一个为图标准备的绘图资源,为按键准备的文本,和一个PendingIntent对象,定义了动作的表现。
你现在可以使用setPriority())方法来告知系统,你的通知的重要性 影响其在列表中的顺序,来设定优先级。你可以传递在Notification类中,由PRIORITY_* 常量定义的五个不同的优先级之一。默认的是PRIORITY_DEFAULT,有两个高于和两个低于它的优先级。
高优先级通知是那些用户一般情况下想要快速回复的通知,如一条即时信息,一条文本信息,或即时事件提醒。低优先级通知为……(官网文档缺失)。
Android 4.0(冰激凌三明治)添加了新的,用来控制系统UI元素可见性的标志位,如使系统栏变暗,或是使其在手机上完全消失。在Android 4.1中,添加了一些更多的标志位,允许你进一步控制系统用户界面的外观和与它们相关的活动布局,通过调用setSystemUiVisibility())方法并传递以下标志位实现:
SYSTEM_UI_FLAG_FULLSCREEN
:隐藏非关键系统UI(如状态栏)。如果你的活动使用了叠加模式的动作条(启用android:windowActionBarOverlay),然后这个标志位同样隐藏动作条,并在使用一个协同动画,同时隐藏和显示两个时也实现相同功能。
SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
:当你启用SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN时,将设置你的活动布局使用相同的屏幕大小,即使系统UI元素仍然可见。虽然部分布局会被系统UI叠加,但当你经常显示和隐藏系统UI时,使用SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN将会非常有用,因为这避免了你的布局需要在每次系统UI显示和隐藏时重新调整新的布局边界。
SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
:当你启用SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION(在Android 4.0时加入)时,将设置你的活动布局使用相同的屏幕大小,即使系统UI元素仍然可见。虽然部分布局会被导航条叠加,但当你经常显示和隐藏系统UI时,使用SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION将会非常有用,因为这避免了你的布局需要在每次导航条显示和隐藏时重新调整新的布局边界。
SYSTEM_UI_FLAG_LAYOUT_STABLE
:当使用SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN和/或SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION时,你可能会想要添加这个标志来,来保证当在一个视图中调用fitSystemWindows())方法时,其被定义的边界始终保持不变,并且考虑可用的屏幕空间。也就是说,通过设置这个标志位,fitSystemWindows())这个方法将表现为,系统UI元素的可见性保持不变,即使你隐藏了所用的系统UI。
更多关于其它相关的系统UI标志位的讨论,请参考Android 4.0中的相关信息。
GridLayout和ViewStub现在可作为远程视频,你可以在你的应用程序小插件布局和自定义通知布局中使用它们。
Android 4.1带来了几种变体和Roboto风格等10种变体字体,并且它们都能被应用程序所使用。你的应用程序现在可以访问全系列的细体和长体字体。
所有可用的的Roboto变体字有:
常规
斜体
粗体
粗斜体
细体
细斜体
常规长体
长斜体
长粗体
长粗斜体
你可以通过新的fontFamily属性与textStyle属性结合,应用上面的任何一种字体
fontFamily所支持的值有:
"scans-serif"为常规的Roboto字体
"scans-serif-light"为细体的Roboto字体
"scans-serif-condensed"为长体的Roboto字体
然后可以通过textStyle应用粗体和斜体,其值分别为"italic"。你可以通过以下方法同时应用两种字体:。
你也可以使用Typeface.create())方法。例如,Typeface.create("sans-serif-light", Typeface.NORMAL)
新的InputManager类允许你查询一组当前连接的输入设备,并注册,当有新的设备被添加,更改,后移除时,得到通知。这个功能非常有用,尤其是在你想建立一个支持多用户的游戏,检测有多少个控制器被接入并且控制器数量发生改变的情况下特别有用。
你可以通过调用getInputDeviceIds())方法来查询所有被接入的输入设备。然后你可能调用getInputDevice())方法获得某个指定设备ID的输入设备-InputDevice
如果你想在有新的输入设备被连接,更改,或断开时得到通知,实现InputManager.InputDeviceListener接口,并通过android.os.Handler) registerInputDeviceListener()注册。
如果接入的输入设备拥有震动功能,你现在可以已存在的Vibrator APIs来控制这些设备的震动,只需要简单的在这些输入设备-InputDevice中调用getVibrator())方法。
以下是新添加的权限:
READ_EXTERNAL_STORAGE
:为外部存储器提供了受保护的读访问权。在Android 4.1中,默认的,所有的应用程序依然有读访问权。在将来的版本中,这个将被改变为要求应用程序显式性地使用这个权限来获得读访问权。如果你的应用程序已经申请了写访问权,那么其将自动获得读访问权。有一个新的开发者选项用来开启读访问限制,对应于将来Android的表现,为开发者测试他们的应用程序提供帮助。
READ_USER_DICTIONARY
:允许应用程序读取用户的字典。这个只应该由IME提出请求,或是一个字典编辑者,如Settings应用。
READ_CALL_LOG
:允许应用程序读取系统的电话日志,包括所有的主叫和被叫电话。
WRITE_CALL_LOG
:允许应用程序修改储存于手机上的系统电话日志。
WRITE_USER_DICTIONARY
:允许应用程序对用户的词典进行写入。
Android 4.1为制备提供了一个新的功能申明:FEATURE_TELEVISION,致力于在电视屏幕上显示用户界面。申明应用程序需要一个电视接口,在manifest文档中使用元素来申明这个功能。
...
这个功能定义的“电视”为典型的客厅电视:在一个大屏幕上显示,用户坐在离屏幕比较远的地方,并且主要的输入方法更向一个方向键,而一般不是通过触摸屏或是鼠标/指示性设备。