【Android】多媒体编程练习MediaPlayer以及notification介绍-第一行代码-第八章(解析)

多彩的手机多媒体世界💫

《第一行代码》在这一章中的重点主要有:notification通知;音频播放;视频播放。知识还是相对局限但是很重点!还是要结合实际的当下的官方文档进行理解可能更有收获。老规矩,先英后中!

MediaPlayer

这个是我个人认为在初步接触安卓多媒体的知识点时最主要的Api;Google提供一个比较良好的功能接口供我们使用,虽然它还推荐使用ExoPlayer,但是我个人认为还是打好基础比较重要一点;

清单权限

使用到多媒体,自然需要一些权限;在官方文档汇总下,主要有两种,第一是网络权限;第二个是Wake Lock 权限。前者很容易理解,有些媒体流需要网络加载例如online 听歌等等;后者主要针对是视频播放,若是希望手机保持亮屏就需要使用到该权限。下面的文字copy是专门针对为啥使用该权限的说明。

If your player application needs to keep the screen from dimming or the processor from sleeping, or uses the MediaPlayer.setScreenOnWhilePlaying() or MediaPlayer.setWakeMode() methods, you must request this permission.

使用资源

MediaPlayer可以进行抓取,解码,播放音视频;主要支持的如下几种资源方式:

  1. 本地资源(app内嵌的)
  2. 内部URI,通过内容提供器进行获取资源;
  3. 外部URL 即 统一资源定位符,一般是通过网络获取;
    官方文档中提供一些代码示例进行参考:
    故特copy一些进行学习。
//通过外部URL进行资源获取
String url = "http://........"; // your URL here
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioAttributes(
    new AudioAttributes.Builder()
        .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
        .setUsage(AudioAttributes.USAGE_MEDIA)
        .build()
);
mediaPlayer.setDataSource(url);
mediaPlayer.prepare(); // might take long! (for buffering, etc)
mediaPlayer.start();

异步准备

异步,同步这几个概念在很久之前学习线程的知识的时候就已经反复强调学习过了。这里还是为了强调避免ANRApplication not response应用程序无响应的出现。

For example, the call to prepare() can take a long time to execute, because it might involve fetching and decoding media data.

例如,prepare方法花费长时间进行媒体数据的抓取解码工作;所以在Ui线程中切勿回调该方法!!!这容易给用户很差的app使用感!
在官网上推荐的解决犯案时使用prepareAsync()该api文档介绍

This method starts preparing the media in the background and returns immediately. 这段描述是官网对于这个方法的肯定!

特别强调—> MediaPlayer的管理状态
原文如下;

The documentation in the MediaPlayer class shows a complete state diagram, that clarifies which methods move the MediaPlayer from one state to another. For example, when you create a new MediaPlayer, it is in the Idle state. At that point, you should initialize it by calling setDataSource(), bringing it to the Initialized state. After that, you have to prepare it using either the prepare() or prepareAsync() method. When the MediaPlayer is done preparing, it enters the Prepared state, which means you can call start() to make it play the media. At that point, as the diagram illustrates, you can move between the Started, Paused and PlaybackCompleted states by calling such methods as start(), pause(), and seekTo(), amongst others. When you call stop(), however, notice that you cannot call start() again until you prepare the MediaPlayer again.

Always keep the state diagram in mind when writing code that interacts with a MediaPlayer object, because calling its methods from the wrong state is a common cause of bugs.要根据其状态进行代码编写才不容易出现一些常见的bugs;
MediaPlayer状态示意图

释放资源

异步处理在很大的程度上是为了考虑资源的利用!MediaPlayer中对于资源的释放方法release()

For example, if you are using a MediaPlayer and your activity receives a call to onStop(), you must release the MediaPlayer, because it makes little sense to hold on to it while your activity is not interacting with the user (unless you are playing media in the background, which is discussed in the next section).

以上引用是为了强调和举例,当activity准备进入OnStop的时候,应该释放该资源以供更加重要的线程使用该资源。

在Service服务中使用MediaPlayer

Service作为android学习的四大重点之一,虽然现在还未比较系统地回顾——这是在《第一行代码》的后面几章中才提及;按照这样的回顾进程来说,到该章节的回顾的时候会重点学习。现在这里的重点还是多媒体的学习,不过这个也可以先稍微提及一些。触类旁通!

You may be wondering what happens if you want to continue playing “background media” even when the user leaves your activity, much in the same way that the built-in Music application behaves.

以上引用介绍在服务中使用MediaPlayer缘由就是为了后台播放————你也不想自己的音乐播放连最基本的后台播放都没吧??!

异步运行

在服务里面进行相应的功能监听——这里使用到很多listener进行监听方法回调。
下面的代码就是一个经典的Service的代码

public class MyService extends Service implements MediaPlayer.OnPreparedListener {
    private static final String ACTION_PLAY = "com.example.action.PLAY";
    MediaPlayer mediaPlayer = null;

    public int onStartCommand(Intent intent, int flags, int startId) {
        ...
        if (intent.getAction().equals(ACTION_PLAY)) {
            mediaPlayer = ... // initialize it here
            mediaPlayer.setOnPreparedListener(this);
            mediaPlayer.prepareAsync(); // prepare async to not block main thread
        }
    }

    /** Called when MediaPlayer is ready */
    public void onPrepared(MediaPlayer player) {//监听是否准备好,避免线程冲突!
        player.start();
    }
}

这些代码中的串联关系还是要参考Api文档才是比较合适的!这里主要是认识一下。

异步异常处理

Error,这里还是使用一个监听OnErrorListener进行异步异常错误的监听;

public class MyService extends Service implements MediaPlayer.OnErrorListener {
    MediaPlayer mediaPlayer;

    public void initMediaPlayer() {
        // ...initialize the MediaPlayer here...
        mediaPlayer.setOnErrorListener(this);
    }

    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
        // ... react appropriately ...
        // The MediaPlayer has moved to the Error state, must be reset!
		//错误监听
    }
}

DRM Digital Rights Management 数字版权管理

这个主要是在高Api中开始的(android 8.0);这个主要关联的Api是MediaDrm
这个章节就不过分深究。多媒体是有版权的,这里是存在商业意义的 ;需要使用时再好好研究一下,毕竟不过是初学者。相关api文档以及介绍

通过Content provider 获取media

这一块就主要附上相应代码:
Content provider的标准写法

ContentResolver contentResolver = getContentResolver();//内容提供器
Uri uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
Cursor cursor = contentResolver.query(uri, null, null, null, null);
if (cursor == null) {
    // query failed, handle error.
} else if (!cursor.moveToFirst()) {
    // no media on the device
} else {
    int titleColumn = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media.TITLE);
    int idColumn = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media._ID);
    do {
       long thisId = cursor.getLong(idColumn);
       String thisTitle = cursor.getString(titleColumn);
       // ...process entry...
    } while (cursor.moveToNext());
}

在以上的基础下加入我们的主角:Media Player

long id = /* retrieve it from somewhere */;
Uri contentUri = ContentUris.withAppendedId(
        android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);

mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioAttributes(
    new AudioAttributes.Builder()
        .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
        .setUsage(AudioAttributes.USAGE_MEDIA)
        .build()
);//进行属性配置
mediaPlayer.setDataSource(getApplicationContext(), contentUri);

// ...prepare and start...

以上是主要的一些知识点,现在准备编写几个demo以巩固学习;我个人认为在《第一行代码》的代码示例有点老旧,看看能不能在网上找到比较好的易懂的案例进行分析,再自己改进学习一下!
参考资料1;参考资料2


Demo的基本思路:

  1. audioDemo:
    多媒体,先尝试一下audio,最基本的就是播放音乐。
    详细文章Demo下载链接
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值