参考书籍:《第一行代码》 第二版 郭霖
如有错漏,请批评指出!
通知(Notification)的使用
我们在使用手机过程中,经常会收到应用程序发出的通知。当某个应用程序希望向用户发送一些提示信息或推送时,就可以借助通知来实现。发出一条通知后,状态栏会显示一个应用图标,下拉状态栏后可以看到通知的详细内容。
- 通知的基本用法
- 首先要获取一个NotificationManager来对通知进行管理。
调用Context的 getSystemService() 方法获取,这个方法接收一个String参数用于确定获取系统的哪个服务,我们传入Context.NOTIFICATION_SERVICE 即可。NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- 接下来需要使用一个Builder构造器来创建 Notification 对象,这里我们使用 support-v4 库中的 NotificationConpat 类的构造器来创建(因为Android系统每次更新版本基本都会对Notification功能进行修改,所以使用app包下的构造器可能存在不稳定性)。
NotificationCompat.Builder() 接收两个参数,第一个参数是Context,第二个参数是一个String,用于对Notification进行分类。我们可以通过一系列的set方法来丰富我们创建的Notification对象。这里我们使用了几个最基本的方法,setContentTitle() 用于设置通知的标题,setContentText()用于设置通知显示的内容,setWhen()用于设置通知创建的时间,setSmallIcon()用于设置状态栏显示的小图标,setLargeIcon()用于设置下拉状态栏中显示的大图标。最后还要调用build()方法来创建Notification对象。Notification notification = new NotificationCompat.Builder(this, "default") .setContentText("通知") .setContentTitle("第一行代码") .setWhen(System.currentTimeMillis()) .setSmallIcon(R.drawable.ic_huaji) .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_android)) .build();
- 然后我们调用 NotificationManager 对象的notify()方法来发送通知。这个方法接收两个参数,第一个参数是id,是通知的唯一标识,第二个参数就是要发送的 Notification 对象。
manager.notify(1, notification);
- 最后,虽然我们的 Notification 创建并且发送出去了,但是我们并没有给这个通知指定事件,当我们点击这个通知时,是没有任何反应的,下面我们来设置点击通知时跳转到某个Activity,并且通知消失。
这里我们调用了setContentIntent()方法,这个方法接收有一个PendingIntent 参数,这种Intent可以理解为一种延时执行的Intent,因为我们在使用Intent时,必须依赖于一个Activity跳转到另一个Activity,否则,我们传递的数据会被清理掉,而我们这里点击通知跳转到另一个Activity,明显发送通知的Activity很多时候并不在后台,因此我们可以理解为,PendingIntent实现Activity跳转的这个动作延时了,当我们点击通知时,才进行跳转。这里由于我们要实现Activity跳转,因此我们调用PendingIntent的getActivity()方法来获取实例,这个方法接收四个参数,第一个参数是Context,第三个参数是一个Intent对象,另两个参数我们传0即可,感兴趣的话可以查看文档,了解每个参数的含义。setAutoCancel()方法用于设置通知被点击时自动取消掉。这里给出的代码是创建以及发送通知的过程,我们需要将这段代码放到某一个Button的点击事件里面,才会触发。直接运行看看效果吧。Intent intent = new Intent(this, CpMainActivity.class); PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0); NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); Notification notification = new NotificationCompat.Builder(this, "default") .setContentText("通知") .setContentTitle("第一行代码") .setWhen(System.currentTimeMillis()) .setSmallIcon(R.drawable.ic_huaji) .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_android)) .setContentIntent(pi) .setAutoCancel(true) .build(); manager.notify(1, notification);
关于通知的内容远不止这么多,我们只是实现了一个简单的通知,Notification.Builder 中提供了很丰富的API,可以帮助我们实现很多炫酷的通知效果,我们这里就不一一介绍了,可以根据自己的需求去查询相关文档。
播放多媒体文件
-
播放音频
在Android中,播放音频一般都是使用Mediaplayer类来实现,它对多种音频提供了非常全面的控制方法,使得播放音乐的工作变得十分简单。
我们先来了解一下Mediaplayer的工作流程:首先创建一个MediaPlayer对象,然后调用setDataSource()方法来设置音频文件的路径,再调用prepare()方法使MediaPlayer进入准备状态,接下来调用start()方法就可以开始播放音频,调用pause()方法可以暂停播放,调用reset()方法可以将Mediaplayer对象重置到刚刚创建的状态,想要再播放音频,就需要重新给它设置音频文件路径;而stop()方法则会使当前Mediaplayer对象无法再播放个音频。
接下来写一个小Demo,首先看一下布局:很简单,就不贴代码了,三个Button,点击Start,开始播放音乐;点击pause,音乐会暂停,再点击start,会从暂停的地方继续播放;点击stop,音乐停止,再点击start,从头开始播放音乐。功能很简单,下面来看代码。
- 首先创建MediaPlayer对象,并进行初始化操作:
private static final int TAG_AUDIO_PERMISSION = 100; private MediaPlayer mMediaPlayer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.mm_activity_audio_and_video); ButterKnife.bind(this); initView(); } private void initView() { mMediaPlayer = new MediaPlayer(); if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, TAG_AUDIO_PERMISSION); }else { initMediaPlayer(); } } private void initMediaPlayer() { try{ File file = new File(Environment.getExternalStorageDirectory(), "music.mp3"); mMediaPlayer.setDataSource(file.getPath()); mMediaPlayer.prepare(); } catch (Exception e) { e.printStackTrace(); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { switch (requestCode) { case TAG_AUDIO_PERMISSION: if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){ initMediaPlayer(); }else { ToastUtil.showShortToast(this, "拒绝权限将无法使用程序"); finish(); } break; default: break; } }
可以看到,我们动态申请了 WRITE_EXTERNAL_STORAGE 这个权限,因为我们要指定音频文件的位置,并读取这个文件,因此我们需要读取手机存储的权限(关于动态权限申请的内容在前面讲过),我们这里主要看关于MediaPlayer的内容。Environment.getExternalStorageDirectory() 这个方法获取的是手机外部存储的根目录,也就是说,我们指定了在手机外部存储的根目录读取 music.mp3 这个文件,为什么读取这个位置呢?当然是因为我在这个目录下准备了一个 music.mp3 音频文件(你可以指定别的位置,只要你在相应的位置放了这个文件)。接下来就是调用 prepare() 方法了,这时我们的 Mediaplayer 对象已经为播放音乐做好了准备。
关于内部存储 和 外部存储 ,我们可能会有疑问,其实在我们使用的智能手机中,无论是手机自带的XXG的内存还是插入SD卡的内存,都属于外部存储。具体可以参考 这篇博客 。- 接下来就是给我们的Button添加点击事件了(使用了 ButterKnife)
@OnClick({R.id.but_start, R.id.but_pause, R.id.but_stop}) public void click(View view) { switch (view.getId()){ default: break; case R.id.but_start: if (!mMediaPlayer.isPlaying()){ mMediaPlayer.start(); } break; case R.id.but_pause: if (mMediaPlayer.isPlaying()){ mMediaPlayer.pause(); } break; case R.id.but_stop: mMediaPlayer.reset(); initMediaPlayer(); break; } }
逻辑很简单,就不解释了。
- 最后别忘了调用 MediaPlayer 对象的 stop() 和 release() 方法将 MediaPlayer相关的资源释放掉。
最后附上 MediaPlayer 相关的常用方法:@Override protected void onDestroy() { super.onDestroy(); if (mMediaPlayer.isPlaying()){ mMediaPlayer.stop(); } if (mMediaPlayer != null){ mMediaPlayer.release(); } }
-
播放视频
播放视频主要使用VideoView 类来实现,其实它的使用方法和Mediaplayer很像。这个类将视频的显示和控制集于一身,是的我们仅仅使用这个类就可以实现一个简单的视频播放器。下面直接看完整的代码吧(包括前面的音频部分)。- 布局部分:
- java代码:
下面也附上 VideoView 的常用方法: 下面来看看 Demo 的实现效果:public class MmAudioAndVideoActivity extends AppCompatActivity { @BindView(R.id.video_view) VideoView mVideoView; private static final int TAG_AUDIO_PERMISSION = 100; private MediaPlayer mMediaPlayer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.mm_activity_audio_and_video); ButterKnife.bind(this); initView(); } private void initView() { mMediaPlayer = new MediaPlayer(); if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, TAG_AUDIO_PERMISSION); }else { initMediaPlayer(); initVideoPath(); } } private void initMediaPlayer() { try{ File file = new File(Environment.getExternalStorageDirectory(), "music.mp3"); mMediaPlayer.setDataSource(file.getPath()); mMediaPlayer.prepare(); } catch (Exception e) { e.printStackTrace(); } } private void initVideoPath() { File file = new File(Environment.getExternalStorageDirectory(), "movie.mp4"); mVideoView.setVideoPath(file.getPath()); } @OnClick({R.id.but_start, R.id.but_pause, R.id.but_stop, R.id.but_start_video, R.id.but_pause_video, R.id.but_replay_video}) public void click(View view) { switch (view.getId()){ default: break; case R.id.but_start: if (!mMediaPlayer.isPlaying()){ mMediaPlayer.start(); } break; case R.id.but_pause: if (mMediaPlayer.isPlaying()){ mMediaPlayer.pause(); } break; case R.id.but_stop: mMediaPlayer.stop(); mMediaPlayer.reset(); initMediaPlayer(); break; case R.id.but_start_video: if (!mVideoView.isPlaying()){ mVideoView.start(); } break; case R.id.but_pause_video: if (mVideoView.isPlaying()){ mVideoView.pause(); } break; case R.id.but_replay_video: mVideoView.resume(); break; } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { switch (requestCode) { case TAG_AUDIO_PERMISSION: if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){ initMediaPlayer(); initVideoPath(); }else { ToastUtil.showShortToast(this, "拒绝权限将无法使用程序"); finish(); } break; default: break; } } @Override protected void onDestroy() { super.onDestroy(); if (mMediaPlayer.isPlaying()){ mMediaPlayer.stop(); } if (mMediaPlayer != null){ mMediaPlayer.release(); } if (mVideoView != null){ mVideoView.suspend(); } } }
上一篇:Android基础回顾(六)| 关于 Content provider
下一篇:Android基础回顾(八)| 使用HTTP协议访问网络