參考書籍:《第一行代碼》 第二版 郭霖
如有錯漏,請批評指出!
通知(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很像。這個類將視頻的顯示和控制集于一身,是的我們僅僅使用這個類就可以實現一個簡單的視頻播放器。下面直接看完整的代碼吧(包括前面的音頻部分)。- 布局部分:
<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>
- java代碼:
下面也附上 VideoView 的常用方法: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協議訪問網絡