在过去,手机的功能都比较单调,仅仅就是用来打电话和发短信。而如今,手机在我们的生活中正扮演着越来越重要的角色,各种娱乐方式都可以在手机上进行。上班的路上太无聊,可以带着耳机听音乐。外出旅游的时候,可以在手机上看电影。无论走到哪里,遇到喜欢的事物都可以随手拍下来。
众多的娱乐方式少不了强大的多媒体的支持,而Android在这方面也做得非常出色。它提供了一系列的API,使得我们可以在程序中调用很多手机的多媒体资源,从而编写出更加丰富多彩的应用程序,本章我们就将对Android中一些常用的多媒体功能的使用进行学习。
前面的7章内容,我们一直都是使用模拟器来运行程序的,不过本章涉及的一些功能必须要在真正手机上运行程序。
8.1 将程序运行到手机上
不必我多说,首先你需要拥有一部Android手机,现在Android手机早就不是什么稀罕物,机会已 经是人手一部了,如果你还没有的话,赶紧去购买吧!
想要将程序运行在手机上,我们需要先通过数据先把手机连接到电脑上。然后进入到设置----->开发者选项界面,并在这个界面中勾选中进行USB调试,如图8.1所示:
注意从Android4.2系统开始,开发者选项默认是隐藏的,你需要先进入到“关于手机”界面,然后对着最下面的版本号那一栏连续点击,就会让开发者显示出来。
然后如果你使用的Windows操作系统,安装完成后就可以看到手机已经连接到电脑上了,如图8.2所示:
现在观察Android Monitor,你会发现当前是有两个设备在线的,一个是我们一直使用的模拟器,另一个则是刚刚连接上的手机了,如图8.3所示。
然后运行一下当前项目,这时不会直接将程序运行到模拟器或者手机上,而是会弹出一个对话框让你进行选择,如图8.4所示:
选中下面的LGE Nexus 5 后点击ok,就会将程序运行到手机上。
8.2 使用通知
通知(Notification)是Android系统中比较有特色的一个功能,当某个应用程序希望向用户发出一些提示信息,而该应用程序又不在前台运行时,就可以借助通知来实现。发出一条通知后,手机最上方的状态栏中会显示一个通知的图标,下拉状态栏后可以看到通知的详细内容。Android的通知功能获得了大量用户的认可和喜爱,就连IOS也是5.0版本之后加入了类似的功能。
8.2.1 通知的基本用法
了解了通知的基本概念,下面我们就来看一下通知的使用方法吧,通知的用法还是比较灵活的,既可以在活动里创建,也可以在广播接收器里创建,当然还可以在下一章中我们将学习的服务里创建。相比于广播接收器和服务,在活动里创建通知的场景还是比较少的,因为一般只有当程序进入到后台的时候我们才需要使用通知。
不过,无论是在哪里创建通知,整体的步骤都是相同的,下面我们就来学习一下创建通知的详细步骤。首先需要一个NotificationManager来对通知进行管理,可以通过调用Context的getSystemService()方法获取到。getSystemService()方法接收一个字符串参数用于确定回去系统的那个服务,这里我们传入Context.NOTIFICATION_SERVICE即可。因此,获取
NotificationManager的实例就可以写成:
接下来需要使用一个Builder构造器来创建Notification对象,但问题在于,几乎Android系统的每一个版本都会对通知这部分功能进行或多或少的修改,API不稳定性问题在通知上显得尤其严重。那么该如何解决这个问题啦?其实解决方案我们之前已经加过好几回了,就是使用support库中提供兼容API。support-v4库中人提供了一个NotificationCompat类,使用这个类的构造器来创建Notification对象,就可以保证我们的程序在所有Android系统版本上都能正常工作了,代码如下所示:
当然,上述代码只是创建了一个空的Notification对象,并没有什么实际作用,我们可以在最终的buidle()方法之前连缀任意多个设置方法来创建一个丰富的Notification对象,先来看一些最基础的设置:
上述代码中一共调用了5各设置方法,下面来一一解析一下。setContentTitle()方法用于指定通知的标题内容,下拉系统状态就可以看到这部分内容。setContentText()方法用于指定通知的正文内容,同样下拉系统状态栏就可以看到这部分内容。setWhen()方法用于指定通知被创建的时间,以毫秒为单位,当下拉系统状态栏时这里指定的时间会显示在相应的通知上。setSmallIcon方法用于设置通知的小图标,注意只能使用纯alpha图层的图片进行设置,小图标会显示在系统状态栏上。setLargeIcon()方法用于设置通知的大图标,当下拉系统状态栏时,就可以看到设置的大图标了。
以上工作都完成之后,只需要调用NotificationManager的notify()方法就可以让通知显示出来了。notify()方法接受两个参数,第一个参数是id,要保证为每个同志所指定的id都是不同的。第二个参数则是Notification对象,这里直接将我们刚刚创建好的Notification对象传入即可。因此,显示一个通知就可以写成:
manager.notify(1,notification);
到这里就已经把创建通知的每一个步骤都解析完了,下面就让我们通过一个具体的例子来看一看通知到底是长什么样的。
新建一个Notification项目,并修改acyivity_main.xml中的代码,如下所示:
可以看到,我们在点击按钮的点击事件里面完成了通知的创建工作,创建的过程正如前面描述所描述的一样。不过这里简单起见,我将通知栏的大小图都直接设置成了ic_launcher这张图,这样就不用再去专门准备图标了,而在实际项目中千万不要这样偷懒。
现在可以运行一下程序了,点击按钮,你会在系统状态栏最左边看到一个小图标,如图8.5所示。
下拉系统状态栏可以看到该通知的详细信息,如图8.6所示。
如果你是用过Android手机,此时应该会下意识的认为这条通知是可以点击的。但是当你去点击它的时候,你会发现需要在代码中进行相应的设置,这就涉及到了一个新的概念。PendingItent。
PendingItent从名字上看起来和Intent有些类似,他们之间也确实存在着不小共同点。比如他们都可以去指明某一个“意图”,都可以用于启动活动、启动服务以及发送广播等。不同的是Intent更倾向于去立即执行某个动作,而PendingItent更倾向于在某个合适的时候去执行某个动作。所以,也可以把PendingItent简单理解为延迟执行的Intent。
PendingItent的用法同样很简单,他主要提供了几个静态方法用于获取PendingIntent的实例,可以根据需求来选择是使用getActivity()方法、getBroadcast()方法,还是getService()方法。这几个方法所接收的参数都是相同的,第一个参数依旧是Context,不用多解释。第二个参数一般用不到,通常传入0即可。第三个参数是Intent对象。我们可以通过这个对象构建出PendingItent的“意图”,第四个参数用于确定PendingItent的行为,有FLAG_ONE_SHOT、FLAG_NO_CREATE、FlAG_CANCEL_CURRENT和FLAG_UPDATE_CURRENT这四种值可以选,没种值的具体含义你可以查看文档,通常情况下这个参数传入0就可以了。
对PendingItent有一定了解后,我们再回过头来看一下NotificationCompat.Builder。这个构造期还可以在连缀一个SetContentIntent方法,接收的参数正是一个PendingItent对象。因此,这里就可以通过PendingItent构建出一个延迟执行的“意图”,当用户点击这条通知时就会执行相应的逻辑。
现在我们来优化一下NotificationTest项目,给刚才通知加上点击功能,让用户点击它的时候可以启动另一个活动。
首先需要准备好另一个活动,右击com.example.notificationtest包----->Activity------->EmptyActivity,新建NotificationActivity,布局名为notification_layout。然后修改notification_layout.xml中的代码。如下所示:
这样就把NotificationActivity这个活动准备好了,下面我们修改MainActivity中的代码,给通知加入点击功能如图所示:(手动创建点击通知跳转)
可以看到,这里先是使用Intent表达出我们想要启动NotificationActivity的“意图”,然后间构建好的Intent对象传入到PendingIntent的getActivity方法里,已得到pendingIntent的实例,接着在NotificationCompat.Builder中调用setContenIntent()方法,把它作为参数传入即可。
现在重新运行以下程序,并点击按钮,有就会发出一条通知。然后下拉系统状态栏,点击一下该通知,就会看到NotificationActivity这个活动界面了,如图8.7所示。
咦?怎么系统状态上的通知图标还没有消失啦?是这样的,如果我们没有在代码中对该通知进行取消,他就会一直显示在系统的状态栏上。解决的方法有两种,一种是在NotificationCompat.Builder中再连缀一个setAutoCancel()方法,一种是现实地调用NotificationManager的cancel()方法将它取消,两种方法我们都来学习一下。
第一种方法写法如下:
可以看到,setAutoCancel()方法传入true,就表示当点击了这个通知的时候,通知会自动取消掉。
第二种方法写法如下:
这里我们在Cancel()方法中传入了1,这里是什么意思啦?还记得在创建通知的时候给每条通知指定的id吗?当时我们给这条通知设置的id就是1.因此,如果你想取消那条通知,在cancel()方法中传入该通知的id就行了。
8.2.2 通知的进阶技巧
现在你已经掌握了创建和取消的方法了,并且知道了如何去响应通知的点击事件。不过通知的用法并不仅仅是这些啦,下面我们就来探究一下通知的更多技巧。
上一小节中创建的通知属于最基本的通知,实际上,NotificationCompat.Builder中提供了非常丰富的API来让我们创建出更加多样的通知效果。当然,每一个API都详细的讲一遍都不太可能,我们只能从中选一些比较常用的API来进行学习。先来看看setSound()方法吧,它可以再通知发出的时候播放一段音频,这样就可以告诉用户通知到来了。setSound()方法接收一个Uri参数,所以在指定音频文件的时候还需要先获取到音频文件对应的URI。比如说,每个手机的/system/media/audio/ringtones目录下都有很多的音频文件,我们可以从中随便选一个音频文件,那么我们在代码中就可以这样指定:
除了允许播放音频外,我们还可以在通知到来的时候让手机进行震动,使用的是vibrate这个属性。它是一个长整型的数组,用于设置手机静止和振动的时长,以毫秒为单位。下标为0的值表示手机静止的时长,下标为1的值表示手机震动的时长,下标为2的值又表示手机静止的时长,以此类推。所以,如果想要让手机再通知到来的时候立刻振动1秒,然后静止1秒,再振动1秒,代码就可以写成:
不过,想要控制手机振动还需要申明权限。因此还得在AndroidManifest.xml文件加入如下声明:
学会了控制通知的声音和振动,下面我们来看一下如何再通知来到时控制手机LED灯的显示。