Android基礎回顧(七)| 使用手機多媒體

參考書籍:《第一行代碼》 第二版 郭霖
如有錯漏,請批評指出!

通知(Notification)的使用

我們在使用手機過程中,經常會收到應用程序發出的通知。當某個應用程序希望向用戶發送一些提示信息或推送時,就可以借助通知來實現。發出一條通知后,狀態欄會顯示一個應用圖標,下拉狀態欄后可以看到通知的詳細內容。

  • 通知的基本用法
  1. 首先要獲取一個NotificationManager來對通知進行管理。
    NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    
    調用Context的 getSystemService() 方法獲取,這個方法接收一個String參數用于確定獲取系統的哪個服務,我們傳入Context.NOTIFICATION_SERVICE 即可。
  2. 接下來需要使用一個Builder構造器來創建 Notification 對象,這里我們使用 support-v4 庫中的 NotificationConpat 類的構造器來創建(因為Android系統每次更新版本基本都會對Notification功能進行修改,所以使用app包下的構造器可能存在不穩定性)。
    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();
    
    NotificationCompat.Builder() 接收兩個參數,第一個參數是Context,第二個參數是一個String,用于對Notification進行分類。我們可以通過一系列的set方法來豐富我們創建的Notification對象。這里我們使用了幾個最基本的方法,setContentTitle() 用于設置通知的標題,setContentText()用于設置通知顯示的內容,setWhen()用于設置通知創建的時間,setSmallIcon()用于設置狀態欄顯示的小圖標,setLargeIcon()用于設置下拉狀態欄中顯示的大圖標。最后還要調用build()方法來創建Notification對象。
  3. 然后我們調用 NotificationManager 對象的notify()方法來發送通知。這個方法接收兩個參數,第一個參數是id,是通知的唯一標識,第二個參數就是要發送的 Notification 對象。
    manager.notify(1, notification);
    
  4. 最后,雖然我們的 Notification 創建并且發送出去了,但是我們并沒有給這個通知指定事件,當我們點擊這個通知時,是沒有任何反應的,下面我們來設置點擊通知時跳轉到某個Activity,并且通知消失。
    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);
    

    這里我們調用了setContentIntent()方法,這個方法接收有一個PendingIntent 參數,這種Intent可以理解為一種延時執行的Intent,因為我們在使用Intent時,必須依賴于一個Activity跳轉到另一個Activity,否則,我們傳遞的數據會被清理掉,而我們這里點擊通知跳轉到另一個Activity,明顯發送通知的Activity很多時候并不在后臺,因此我們可以理解為,PendingIntent實現Activity跳轉的這個動作延時了,當我們點擊通知時,才進行跳轉。這里由于我們要實現Activity跳轉,因此我們調用PendingIntent的getActivity()方法來獲取實例,這個方法接收四個參數,第一個參數是Context,第三個參數是一個Intent對象,另兩個參數我們傳0即可,感興趣的話可以查看文檔,了解每個參數的含義。setAutoCancel()方法用于設置通知被點擊時自動取消掉。這里給出的代碼是創建以及發送通知的過程,我們需要將這段代碼放到某一個Button的點擊事件里面,才會觸發。直接運行看看效果吧。

關于通知的內容遠不止這么多,我們只是實現了一個簡單的通知,Notification.Builder 中提供了很豐富的API,可以幫助我們實現很多炫酷的通知效果,我們這里就不一一介紹了,可以根據自己的需求去查詢相關文檔。

播放多媒體文件

  • 播放音頻
    在Android中,播放音頻一般都是使用Mediaplayer類來實現,它對多種音頻提供了非常全面的控制方法,使得播放音樂的工作變得十分簡單。
    我們先來了解一下Mediaplayer的工作流程:首先創建一個MediaPlayer對象,然后調用setDataSource()方法來設置音頻文件的路徑,再調用prepare()方法使MediaPlayer進入準備狀態,接下來調用start()方法就可以開始播放音頻,調用pause()方法可以暫停播放,調用reset()方法可以將Mediaplayer對象重置到剛剛創建的狀態,想要再播放音頻,就需要重新給它設置音頻文件路徑;而stop()方法則會使當前Mediaplayer對象無法再播放個音頻。
    接下來寫一個小Demo,首先看一下布局:

    很簡單,就不貼代碼了,三個Button,點擊Start,開始播放音樂;點擊pause,音樂會暫停,再點擊start,會從暫停的地方繼續播放;點擊stop,音樂停止,再點擊start,從頭開始播放音樂。功能很簡單,下面來看代碼。

    1. 首先創建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卡的內存,都屬于外部存儲。具體可以參考 這篇博客 。

    1. 接下來就是給我們的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;
        }
    }
    

    邏輯很簡單,就不解釋了。

    1. 最后別忘了調用 MediaPlayer 對象的 stop() 和 release() 方法將 MediaPlayer相關的資源釋放掉。
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mMediaPlayer.isPlaying()){
            mMediaPlayer.stop();
        }
        if (mMediaPlayer != null){
            mMediaPlayer.release();
        }
    }
    

    最后附上 MediaPlayer 相關的常用方法:
  • 播放視頻
    播放視頻主要使用VideoView 類來實現,其實它的使用方法和Mediaplayer很像。這個類將視頻的顯示和控制集于一身,是的我們僅僅使用這個類就可以實現一個簡單的視頻播放器。下面直接看完整的代碼吧(包括前面的音頻部分)。

    1. 布局部分:
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".multimedia.MmAudioAndVideoActivity">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:layout_marginTop="24dp">
    
            <Button
                android:id="@+id/but_start"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/start"
                android:textAllCaps="false"
                tools:ignore="ButtonStyle" />
    
            <Button
                android:id="@+id/but_pause"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="24dp"
                android:text="@string/pause"
                android:textAllCaps="false"
                tools:ignore="ButtonStyle" />
    
            <Button
                android:id="@+id/but_stop"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="24dp"
                android:text="@string/stop"
                android:textAllCaps="false"
                tools:ignore="ButtonStyle" />
    
        </LinearLayout>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:layout_marginTop="20dp">
    
            <VideoView
                android:id="@+id/video_view"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_horizontal">
    
                <Button
                    android:id="@+id/but_start_video"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@string/start"
                    android:textAllCaps="false"
                    tools:ignore="ButtonStyle" />
    
                <Button
                    android:id="@+id/but_pause_video"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="24dp"
                    android:text="@string/pause"
                    android:textAllCaps="false"
                    tools:ignore="ButtonStyle" />
    
                <Button
                    android:id="@+id/but_replay_video"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="24dp"
                    android:text="@string/replay"
                    android:textAllCaps="false"
                    tools:ignore="ButtonStyle" />
            </LinearLayout>
    
        </LinearLayout>
    
    </LinearLayout>
    
    1. java代碼:
    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();
            }
        }
    }
    

    下面也附上 VideoView 的常用方法:

    下面來看看 Demo 的實現效果:

上一篇:Android基礎回顧(六)| 關于 Content provider
下一篇:Android基礎回顧(八)| 使用HTTP協議訪問網絡


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容