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

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

通知(Notification)的使用

我們在使用手機過程中夫啊,經常會收到應用程序發(fā)出的通知顿肺。當某個應用程序希望向用戶發(fā)送一些提示信息或推送時,就可以借助通知來實現性昭。發(fā)出一條通知后拦止,狀態(tài)欄會顯示一個應用圖標,下拉狀態(tài)欄后可以看到通知的詳細內容糜颠。

  • 通知的基本用法
  1. 首先要獲取一個NotificationManager來對通知進行管理汹族。
    NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    
    調用Context的 getSystemService() 方法獲取,這個方法接收一個String參數用于確定獲取系統(tǒng)的哪個服務其兴,我們傳入Context.NOTIFICATION_SERVICE 即可顶瞒。
  2. 接下來需要使用一個Builder構造器來創(chuàng)建 Notification 對象,這里我們使用 support-v4 庫中的 NotificationConpat 類的構造器來創(chuàng)建(因為Android系統(tǒng)每次更新版本基本都會對Notification功能進行修改忌警,所以使用app包下的構造器可能存在不穩(wěn)定性)搁拙。
    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方法來豐富我們創(chuàng)建的Notification對象。這里我們使用了幾個最基本的方法盐茎,setContentTitle() 用于設置通知的標題兴垦,setContentText()用于設置通知顯示的內容,setWhen()用于設置通知創(chuàng)建的時間字柠,setSmallIcon()用于設置狀態(tài)欄顯示的小圖標探越,setLargeIcon()用于設置下拉狀態(tài)欄中顯示的大圖標。最后還要調用build()方法來創(chuàng)建Notification對象窑业。
  3. 然后我們調用 NotificationManager 對象的notify()方法來發(fā)送通知钦幔。這個方法接收兩個參數,第一個參數是id常柄,是通知的唯一標識鲤氢,第二個參數就是要發(fā)送的 Notification 對象。
    manager.notify(1, notification);
    
  4. 最后西潘,雖然我們的 Notification 創(chuàng)建并且發(fā)送出去了卷玉,但是我們并沒有給這個通知指定事件,當我們點擊這個通知時喷市,是沒有任何反應的相种,下面我們來設置點擊通知時跳轉到某個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可以理解為一種延時執(zhí)行的Intent缭黔,因為我們在使用Intent時食茎,必須依賴于一個Activity跳轉到另一個Activity,否則馏谨,我們傳遞的數據會被清理掉别渔,而我們這里點擊通知跳轉到另一個Activity,明顯發(fā)送通知的Activity很多時候并不在后臺惧互,因此我們可以理解為哎媚,PendingIntent實現Activity跳轉的這個動作延時了,當我們點擊通知時喊儡,才進行跳轉拨与。這里由于我們要實現Activity跳轉,因此我們調用PendingIntent的getActivity()方法來獲取實例艾猜,這個方法接收四個參數买喧,第一個參數是Context捻悯,第三個參數是一個Intent對象,另兩個參數我們傳0即可淤毛,感興趣的話可以查看文檔今缚,了解每個參數的含義。setAutoCancel()方法用于設置通知被點擊時自動取消掉低淡。這里給出的代碼是創(chuàng)建以及發(fā)送通知的過程姓言,我們需要將這段代碼放到某一個Button的點擊事件里面,才會觸發(fā)蔗蹋。直接運行看看效果吧何荚。

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

播放多媒體文件

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

    很簡單,就不貼代碼了狞谱,三個Button乃摹,點擊Start,開始播放音樂跟衅;點擊pause孵睬,音樂會暫停,再點擊start伶跷,會從暫停的地方繼續(xù)播放掰读;點擊stop秘狞,音樂停止,再點擊start蹈集,從頭開始播放音樂烁试。功能很簡單,下面來看代碼雾狈。

    1. 首先創(chuàng)建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;
        }
    }
    

    可以看到,我們動態(tài)申請了 WRITE_EXTERNAL_STORAGE 這個權限善榛,因為我們要指定音頻文件的位置辩蛋,并讀取這個文件,因此我們需要讀取手機存儲的權限(關于動態(tài)權限申請的內容在前面講過)移盆,我們這里主要看關于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協(xié)議訪問網絡


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末奸绷,一起剝皮案震驚了整個濱河市梗夸,隨后出現的幾起案子,更是在濱河造成了極大的恐慌号醉,老刑警劉巖反症,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件辛块,死亡現場離奇詭異,居然都是意外死亡铅碍,警方通過查閱死者的電腦和手機润绵,發(fā)現死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來胞谈,“玉大人尘盼,你說我怎么就攤上這事》成” “怎么了卿捎?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長径密。 經常有香客問我午阵,道長,這世上最難降的妖魔是什么享扔? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任底桂,我火速辦了婚禮,結果婚禮上惧眠,老公的妹妹穿的比我還像新娘籽懦。我一直安慰自己,他們只是感情好氛魁,可當我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布猫十。 她就那樣靜靜地躺著,像睡著了一般呆盖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上贷笛,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天应又,我揣著相機與錄音,去河邊找鬼乏苦。 笑死株扛,一個胖子當著我的面吹牛,可吹牛的內容都是我干的汇荐。 我是一名探鬼主播洞就,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼掀淘!你這毒婦竟也來了旬蟋?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤革娄,失蹤者是張志新(化名)和其女友劉穎倾贰,沒想到半個月后冕碟,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡匆浙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年安寺,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片首尼。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡挑庶,死狀恐怖,靈堂內的尸體忽然破棺而出软能,到底是詐尸還是另有隱情迎捺,我是刑警寧澤,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布埋嵌,位于F島的核電站破加,受9級特大地震影響,放射性物質發(fā)生泄漏雹嗦。R本人自食惡果不足惜范舀,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望了罪。 院中可真熱鬧锭环,春花似錦、人聲如沸泊藕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽娃圆。三九已至玫锋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間讼呢,已是汗流浹背撩鹿。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留悦屏,地道東北人节沦。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像础爬,于是被迫代替她去往敵國和親甫贯。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內容