關於Android中通知欄的講解及適配Android 8.0
前言
通知欄是Android系統原創的一個功能,雖然喬布斯一直認為Android系統是徹徹底底抄襲IOS的一個產品,但是通知欄確實是Android系統原創的,反而蘋果在ios 5之後也加入了類似的通知欄功能。
通知欄的設計非常巧妙,他預設情況下不佔用任何空間,只有當用戶需要的時候用手指在狀態列上向下滑動,通知欄的內容才會顯示出來,極大地解決了手機螢幕過小,內容展示區域不足的問題。
可能有的讀者比較好奇那麼ios 5 之前未引入通知欄功能的時候,iPhone都是怎樣進行訊息通知的呢?使用的就是未讀角標的功能,效果圖如下:
最後當然這一功能也被很多國產手機廠商所模仿,紛紛推出了自己的角標功能,其中很多都是通過向系統傳送廣播的方式來實現的,同時由於該角標功能的實現GooGle官方並沒有給出統一的api,因此導致了各大手機廠商的廣播標準“隨意”指定,互不相容,從而在我們開發過程中實現該角標功能的時候為了考慮相容性而導致程式碼混亂,讓開發者頭疼。
值的高興的是,從Android 8.0開始,Google制定了Android系統上的角標規範,同時也提供了標準api,以上讓開發者頭疼的問題現在也終於得到了解決,關於該角標功能的官方實現是作為8.0通知欄功能更新的一部分而新增的,在文章後面講解8.0通知欄時我們會詳細講解,此處提及只是先讓開發者粗略瞭解一下角標和通知欄的存在背景相關的知識。
Android 7.0適配及微技巧講解
8.0適配之前我們先來了解一下7.0適配的一些知識,然後引出8.0適配,循序漸進方便讀者理解。
Android系統上的通知欄功能隨著不同版本的釋出幾乎一直都在做調整,尤其是7.0版本又對通知欄做了比較大的調整,這樣就導致新版本的通知欄API無法相容老的版本,這對開發者來說確實是一件比較頭疼的事情,而Google官方當然也是意識到了這一點,為此Android在appcompat-v7庫中提供了一個NotificationCompat的類來自動幫我們進行所有系統版本的相容性處理。
使用NotificationCompat類建立通知欄的程式碼示例如下:
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
Notification notification = builder
.setContentTitle("這是通知標題")
.setContentText("這是通知內容" )
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.build();
manager.notify(1, notification);
可以看到,這裡只是把我們平時使用的Notification.Builder改成了NotificationCompat.Builder而已,其他用法都是一模一樣的,這樣我們的通知就具備各種Android版本的相容性了。
注意看一下我們給通知設定的圖示,一個小圖示、一個大圖示,都是使用的R.mipmap.ic_launcher這張圖。其實很多app都使用的這種做法,即直接拿應用程式的icon來作為通知的圖示,好像這樣看上去也挺合理的。
現在我使用Android 6.0系統的Nexus 5手機執行這個程式,並觸發上面那段通知邏輯,效果如圖下圖所示:
可以看到,通知欄上彈出了一個通知圖示。然後我們將通知欄下拉展開,效果如下圖所示:
效果好像還不錯的樣子。但實際上,我現在是將專案的targetSdkVersion指定成了21以下,即低於5.0系統。如果將targetSdkVersion指定成21或者更高的話,結果可能就不樂觀了:
defaultConfig {
....
targetSdkVersion 23
}
這裡我們將targetSdkVersion指定成了23,然後重新執行程式並觸發圖示邏輯,效果如下圖所示:
恩?這是什麼鬼,怎麼通知圖示變成白白的一個圓了。下拉之後的大圖效果如下:
好像下拉之後的大圖還算正常,不過大圖的右下角也有一個白白的圓。
這到底是為什麼呢?實際上,Android從5.0系統開始,對於通知欄圖示的設計進行了修改。現在Google要求,所有應用程式的通知欄圖示,應該只使用alpha圖層來進行繪製,而不應該包括RGB圖層。
說的好像很玄乎,什麼叫作只使用alpha圖層來進行繪製呢?其實通俗點來講,就是讓我們的通知欄圖示不要帶顏色就可以了。
恩?不帶顏色!那圖示還怎麼設計?但這就不是我們程式設計師應該考慮的問題了,而是應該交給專案的UI設計師來想辦法,但我們需要將這個設計需求清楚地告訴設計師,因為他們通常並不知道Google的各種標準和要求。
那麼我們來參考一下別的程式都是怎麼設計通知欄圖示的,這是支付寶的通知欄圖示:
下拉通知之後的效果是這樣的:
然後再看一下網易新聞的通知欄圖示:
下拉通知之後的效果是這樣的:
可以看出,它們的通知欄小圖都是沒有RGB色的,圖示是隻有白色一種顏色,然後藉助alpha圖層來繪製出一個logo的樣式。
因此,按著這種設計要求,我將專案的通知欄圖示改成了這個樣子:
這張圖只用於替換通知的小圖部分,大圖仍然還是用原來的那樣圖就可以了。現在重新執行一下程式,效果如下圖所示:
這樣看上去效果就好多了吧?然後下拉通知欄之後的效果如下圖所示:
這裡我們來仔細觀察一下這個下拉後的大圖,其實前面大家應該也已經注意到了,只不過一直沒提,在大圖示的右下角,還有一個比較小的圓圈,在這個圓圈中巢狀著我們設定的小圖示。
這個功能是系統自動附加的一個功能,並不需要我們進行任何的程式碼設定,可以觀察一下,支付寶、網易新聞也都是有這個功能的。但是如果我們再看仔細一點,你會發現網易的圖示更好看一些,因為系統給右下角的這個小圓圈預設是設定成灰色的,和我們的整體色調並不搭配,而網易則將這個小圓圈改成了紅色,因此總體視覺效果更好。
那麼怎樣修改這個小圓圈的顏色呢?其實非常簡單,只需要在NotificationCompat.Builder中再多連綴一個setColor()方法就可以了,如下所示:
Notification notification = builder
......
.setColor(Color.parseColor("#EAA935"))
.build();
現在重新執行一下程式,通知欄大圖的具體效果如下圖所示:
怎麼樣,現在的效果是不是更棒了,但是這裡我還要給大家提個醒,上面的功能我使用Nexus手機和三星手機都測試過,結果都是正常的,但是使用小米手機測試就比較無語了,MIUI系統直接無視我們設定的大圖和小圖,一律使用應用程式的icon來作為通知欄圖示,所以如果你是使用的小米手機,就測試不出來上述的各種效果了。其他手機的相容性我還沒有試過,不過不管怎麼樣,我們的程式碼都是要這麼寫的,至於那些定製過的系統該如何去解析展示,那是這些第三方廠商的事情,畢竟我們程式設計師也是控制不了的。
當然,如果你手上只有小米手機的話,也不要絕望,還是可以使用Android模擬器來測試這個功能的。
Android 8.0 適配以及角標功能的實現
關於Android系統原創的通知欄設計,確實是一個很巧妙又很實用的功能,但是該功能卻遭到了廣大應用開發者的濫用,各個App都希望能搶佔通知欄的空間,來儘可能地宣傳和推廣自己的產品。現在經常是早上一覺醒來拿起手機一看,通知欄上全是各種APP的推送,不勝其煩。
我個人雖然是Android應用開發者,但同時也是Android手機的資深使用者。我已經使用了8年的Android手機,目前我對於通知欄的這種垃圾推送是零容忍的。現在每當我安裝一個新的App時,我都會先到設定裡面去找一找有沒有推送開關,如果有的話我會第一時間把它關掉。而如果一個App經常給我推送垃圾資訊卻又無法關閉時,我會直接將它的通知總開關給關掉,如果還不是什麼重要的App的話,那麼我可能就直接將它解除安裝掉了。
每個開發者都只想著儘可能地去宣傳自己的App,最後使用者的手機就亂得跟雞窩一樣了。但是通知欄又還是有用處的,比如我們收到微信、簡訊等訊息的時候,確實需要通知欄給我們提醒。因此分析下來,通知欄目前最大的問題就是,無法讓使用者對感興趣和不感興趣的訊息進行區分。就比如說,我希望淘寶向我推送賣家發貨和物流的相關訊息,但是我不想收到那些打折促銷或者是讓我去買衣服的這類訊息。那麼就目前來說,是沒有辦法對這些訊息做區分的,我要麼同意接受所有訊息,要麼就遮蔽所有訊息,這是當前通知欄的痛點。
那麼在Android 8.0系統中,Google也是從這個痛點開始下手的,從Android 8.0系統開始,Google引入了 通知渠道 這個概念。
什麼是通知渠道呢?顧名思義,就是每條通知都要屬於一個對應的渠道。每個App都可以自由地建立當前App擁有哪些通知渠道,但是這些通知渠道的控制權都是掌握在使用者手上的。使用者可以自由地選擇這些通知渠道的重要程度,是否響鈴、是否振動、或者是否要關閉這個渠道的通知。
擁有了這些控制權之後,使用者就再也不用害怕那些垃圾推送訊息的打擾了,因為使用者可以自主地選擇自己關心哪些通知、不關心哪些通知。舉個具體的例子,我希望可以即時收到支付寶的收款資訊,因為我不想錯過任何一筆收益,但是我又不想收到支付寶給我推薦的周圍美食,因為我沒錢只吃得起公司食堂。這種情況,支付寶就可以建立兩種通知渠道,一個收支,一個推薦,而我作為使用者對推薦類的通知不感興趣,那麼我就可以直接將推薦通知渠道關閉,這樣既不影響我關心的通知,又不會讓那些我不關心的通知來打擾我了。
對於每個App來說,通知渠道的劃分是非常需要仔細考究的,因為通知渠道一旦建立之後就不能再修改了,因此開發者需要仔細分析自己的App一共有哪些型別的通知,然後再去建立相應的通知渠道。
我們是否一定要對通知進行渠道適配?
建議:如果你將專案中的targetSdkVersion指定到了26或者更高,那麼一定要適配。
首先,如果你升級了appcompat庫,那麼所有使用appcompat庫來構建通知的地方全部都會進行廢棄方法提示,如下所示:
上圖告訴我們,此方法已廢棄,需要使用帶有通知渠道的方法才行。
當然,Google也並沒有完全做絕,即使方法標為了廢棄,但還是可以正常使用的。可是如果你將專案中的targetSdkVersion指定到了26或者更高,那麼Android系統就會認為你的App已經做好了8.0系統的適配工作,當然包括了通知欄的適配。這個時候如果還不使用通知渠道的話,那麼你的App的通知將完全無法彈出。因此這裡給大家的建議就是,一定要適配。
那麼如何進行通知渠道的適配?
首先我們使用Android Studio來新建一個專案,就叫它NotificationTest吧。
建立好專案之後,開啟app/build.gradle檔案檢查一下,確保targetSdkVersion已經指定到了26或者更高,如下所示:
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.example.notificationtest"
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
}
可以看到,這裡我在建立新專案的時候預設targetSdkVersion就是26,如果你是低於26的話,說明你的Android SDK有些老了,最好還是更新一下。當然如果你懶得更新也沒關係,手動把它改成26就可以了。
首先我們需要仔細分析自己的App一共有哪些型別的通知,然後再去建立相應的通知渠道:
接下來修改MainActivity中的程式碼,如下所示:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String channelId = "chat";
String channelName = "聊天訊息";
int importance = NotificationManager.IMPORTANCE_HIGH;
createNotificationChannel(channelId, channelName, importance);
channelId = "subscribe";
channelName = "訂閱訊息";
importance = NotificationManager.IMPORTANCE_DEFAULT;
createNotificationChannel(channelId, channelName, importance);
}
}
@TargetApi(Build.VERSION_CODES.O)
private void createNotificationChannel(String channelId, String channelName, int importance) {
NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);
NotificationManager notificationManager = (NotificationManager) getSystemService(
NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);
}
}
這裡我們在MainActivity中建立了兩個通知渠道,首先要確保的是當前手機的系統版本必須是Android 8.0系統或者更高,因為低版本的手機系統並沒有通知渠道這個功能,不做系統版本檢查的話會在低版本手機上造成崩潰。
上面建立通知渠道的這部分程式碼,你可以寫在MainActivity中,也可以寫在Application中,實際上可以寫在程式的任何位置,只需要保證在通知彈出之前呼叫就可以了。並且建立通知渠道的程式碼只在第一次執行的時候才會建立,以後每次執行建立程式碼系統會檢測到該通知渠道已經存在了,因此不會重複建立,也並不會影響任何效率。
建立一個通知渠道的方式非常簡單,這裡我封裝了一個createNotificationChannel()方法,裡面的邏輯相信大家都看得懂。需要注意的是,建立一個通知渠道至少需要渠道ID、渠道名稱以及重要等級這三個引數,其中渠道ID可以隨便定義,只要保證全域性唯一性就可以。渠道名稱是給使用者看的,需要能夠表達清楚這個渠道的用途。重要等級的不同則會決定通知的不同行為,當然這裡只是初始狀態下的重要等級,使用者可以隨時手動更改某個渠道的重要等級,App是無法干預的。
上述程式碼我是模擬了這樣一個場景。想象一下我們正在開發一個類似於微信的App,其中App通知主要可以分為兩類,一類是我和別人的聊天訊息,這類訊息非常重要,因此重要等級我設為了IMPORTANCE_HIGH。另一類是公眾號的訂閱訊息,這類訊息不是那麼重要,因此重要等級我設為了IMPORTANCE_DEFAULT。除此之外,重要等級還可以設定為IMPORTANCE_LOW、IMPORTANCE_MIN,分別對應了更低的通知重要程度。
現在就可以執行一下程式碼了,執行成功之後我們關閉App,進入到設定 -> 應用 -> 通知當中,檢視NotificationTest這個App的通知介面,如下圖所示:
剛才我們建立的兩個通知渠道這裡已經顯示出來了。可以看到,由於這兩個通知渠道的重要等級不同,通知的行為也是不同的,聊天訊息可以發出提示音並在螢幕上彈出通知,而訂閱訊息只能發出提示音。
當然,使用者還可以點選進去對該通知渠道進行任意的修改,比如降低聊天訊息的重要等級,甚至是可以完全關閉該渠道的通知。
然後建立通知時指定它屬於哪個渠道:
繼續修改activity_main.xml中的程式碼,如下所示:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="傳送聊天訊息"
android:onClick="sendChatMsg"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="傳送訂閱訊息"
android:onClick="sendSubscribeMsg"
/>
</LinearLayout>
這裡我們在佈局檔案中加入了兩個按鈕,很顯然,一個是用於觸發聊天訊息渠道通知的,一個是用於觸發訂閱訊息渠道通知的。
接下來在MainActivity中繼續新增建立屬於指定渠道通知的程式碼,如下所示:
public class MainActivity extends AppCompatActivity {
...
public void sendChatMsg(View view) {
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification notification = new NotificationCompat.Builder(this, "chat")
.setContentTitle("收到一條聊天訊息")
.setContentText("今天中午吃什麼?")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.icon)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.icon))
.setAutoCancel(true)
.build();
manager.notify(1, notification);
}
public void sendSubscribeMsg(View view) {
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification notification = new NotificationCompat.Builder(this, "subscribe")
.setContentTitle("收到一條訂閱訊息")
.setContentText("地鐵沿線30萬商鋪搶購中!")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.icon)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.icon))
.setAutoCancel(true)
.build();
manager.notify(2, notification);
}
}
上面省略號表示的即是上面建立通知渠道號的程式碼,你也可以將這部分程式碼放到你自己的Application類中去指定。
這裡我們分別在sendChatMsg()和sendSubscribeMsg()方法中觸發了兩條通知,建立通知的程式碼就不再多做解釋了,和傳統建立通知的方法沒什麼兩樣,只是在NotificationCompat.Builder中需要多傳入一個通知渠道ID,那麼這裡我們分別傳入了chat和subscribe這兩個剛剛建立的渠道ID。
現在重新執行一下程式碼,並點擊發送聊天訊息按鈕,效果如下圖所示:
由於這是一條重要等級高的通知,因此會使用這種螢幕彈窗的方式來通知使用者有訊息到來。然後我們可以下拉展開通知欄,這裡也能檢視到通知的詳細資訊:
使用者可以通過快速向左或者向右滑動來關閉這條通知。
接下來點擊發送訂閱訊息按鈕,你會發現現在螢幕上不會彈出一條通知提醒了,只會在狀態列上顯示一個小小的通知圖示:
因為訂閱訊息通知的重要等級是預設級別,這就是預設級別通知的展示形式。當然我們還是可以下拉展開通知欄,檢視通知的詳細資訊:
不過上面演示的都是通知欄的傳統功能,接下來我們看一看Android 8.0系統中通知欄特有的功能。
剛才提到了,快速向左或者向右滑動可以關閉一條通知,但如果你緩慢地向左或者向右滑動,就會看到這樣兩個按鈕:
其中,左邊那個時鐘圖示的按鈕可以讓通知延遲顯示。比方說這是一條比較重要的通知,但是我暫時沒時間看,也不想讓它一直顯示在狀態列裡打擾我,我就可以讓它延遲一段後時間再顯示,這樣我就暫時能夠先將精力放在專注的事情上,等過會有時間了這條通知會再次顯示出來,我不會錯過任何資訊。如下所示:
而右邊那個設定圖示的按鈕就可以用來對通知渠道進行遮蔽和配置了,使用者對每一個App的每一個通知渠道都有絕對的控制權,可以根據自身的喜好來進行配置和修改。如下所示:
比如說我覺得訂閱訊息老是向我推薦廣告,實在是太煩了,我就可以將訂閱訊息的通知渠道關閉掉。這樣我以後就不會再收到這個通知渠道下的任何訊息,而聊天訊息卻不會受到影響,這就是8.0系統通知渠道最大的特色。
另外,點選上圖中的所有類別就可以進入到當前應用程式通知的完整設定介面。
開發者如何管理通知渠道?
在前面的內容中我們已經瞭解到,通知渠道一旦建立之後就不能再通過程式碼修改了。既然不能修改的話那還怎麼管理呢?為此,Android賦予了開發者讀取通知渠道配置的許可權,如果我們的某個功能是必須按照指定要求來配置通知渠道才能使用的,那麼就可以提示使用者去手動更改通知渠道配置。
比如我們開發的是一個類似於微信的App,聊天訊息是至關重要的,如果使用者不小心將聊天訊息的通知渠道給關閉了,那豈不是所有重要的資訊全部都丟了?為此我們一定要保證使用者打開了聊天訊息的通知渠道才行。
我們繼續修改MainActivity中的程式碼,如下所示:
public class MainActivity extends AppCompatActivity {
...
public void sendChatMsg(View view) {
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = manager.getNotificationChannel("chat");
if (channel.getImportance() == NotificationManager.IMPORTANCE_NONE) {
Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
intent.putExtra(Settings.EXTRA_CHANNEL_ID, channel.getId());
startActivity(intent);
Toast.makeText(this, "請手動將通知開啟", Toast.LENGTH_SHORT).show();
}
}
Notification notification = new NotificationCompat.Builder(this, "chat")
...
.build();
manager.notify(1, notification);
}
...
}
這裡我們對sendChatMsg()方法進行了修改,通過getNotificationChannel()方法獲取到了NotificationChannel物件,然後就可以讀取該通知渠道下的所有配置了。這裡我們判斷如果通知渠道的importance等於IMPORTANCE_NONE,就說明使用者將該渠道的通知給關閉了,這時會跳轉到通知的設定介面提醒使用者手動開啟。
現在重新執行一下程式,效果如下圖所示:
可以看到,當我們將聊天訊息的通知渠道關閉後,下次再次傳送聊天訊息將會直接跳轉到通知設定介面,提醒使用者手動將通知開啟。
除了以上管理通知渠道的方式之外,Android 8.0還賦予了我們刪除通知渠道的功能,只需使用如下程式碼即可刪除:
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.deleteNotificationChannel(channelId);
但是這個功能非常不建議大家使用。因為Google為了防止應用程式隨意地建立垃圾通知渠道,會在通知設定介面顯示所有被刪除的通知渠道數量,如下圖所示:
這樣是非常不美觀的,所以對於開發者來說最好的做法就是仔細規劃好通知渠道,而不要輕易地使用刪除功能。
Android 角標實現標準API
接下來我們就來學習一下如何在Android系統上實現未讀角標的效果。
繼續修改MainActivity中的程式碼,如下所示:
public class MainActivity extends AppCompatActivity {
...
@TargetApi(Build.VERSION_CODES.O)
private void createNotificationChannel(String channelId, String channelName, int importance) {
NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);
channel.setShowBadge(true);
NotificationManager notificationManager = (NotificationManager) getSystemService(
NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);
}
public void sendSubscribeMsg(View view) {
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification notification = new NotificationCompat.Builder(this, "subscribe")
...
.setNumber(2)
.build();
manager.notify(2, notification);
}
}
可以看到,這裡我們主要修改了兩個地方。第一是在建立通知渠道的時候,呼叫了NotificationChannel的setShowBadge(true)方法,表示允許這個渠道下的通知顯示角標。第二是在建立通知的時候,呼叫了setNumber()方法,並傳入未讀訊息的數量。
現在重新執行一下程式,並點擊發送訂閱訊息按鈕,然後在Launcher中找到NotificationTest這個應用程式,如下圖所示:
可以看到,在圖示的右上角有個綠色的角標,說明我們編寫的角標功能已經生效了。
需要注意的是,即使我們不呼叫setShowBadge(true)方法,Android系統預設也是會顯示角標的,但是如果你想禁用角標功能,那麼記得一定要呼叫setShowBadge(false)方法。
但是未讀數量怎麼沒有顯示出來呢?這個功能還需要我們對著圖示進行長按才行,效果如下圖所示:
這樣就能看到通知的未讀數量是2了。
可能有些朋友習慣了iOS上的那種未讀角標,覺得Android上這種還要長按的方式很麻煩。這個沒有辦法,因為這畢竟是Android原生系統,Google沒有辦法像國內手機廠商那樣可以肆無忌憚地模仿iOS,要不然可能會吃官司的。但是我相信國內手機廠商肯定會將這部分功能進行定製,風格應該會類似於iOS。不過這都不重要,對於我們開發者來說,最好的福音就是有了統一的API標準,不管國內手機廠商以後怎麼定製ROM,都會按照這個API的標準來定製,我們只需要使用這個API來進行程式設計就可以了。
本文轉載自:https://blog.csdn.net/guolin_blog/article/details/79854070