Android Notification實現(xiàn)動態(tài)顯示通話時間
基于android N MTK釋放的源碼,供大家參考,具體內(nèi)容如下
本文主要講解如何在 IncallUI 的notification 上面不停地更新顯示當前已通話多長時間,從而達到和incallUI通話界面上的通話時間一致。
主要思路
1、我們需要知道通話建立時的時間,即call 的狀態(tài)從 INCOMING或者DIALING 轉(zhuǎn)變成ACTIVE的時候
2、時間每秒鐘都會發(fā)生變化,所以我們就需要不停的更新notification的界面,我們這里是不停的創(chuàng)建和notify同一個notification,已到達更新時間的效果
3、我們需要CallTimer線程不停的幫我們計算時間,并控制界面的更新
代碼實現(xiàn)
這里是在源碼incallUI目錄下的StatusBarNotifier.java中修改
....省略部分代碼
//震動時長,這里為不振動
private static final long[] IN_CALL_VIBRATE_PATTERN_NULL = new long[] {0, 0, 0};
//線程隔多久執(zhí)行一次已ms為單位,這里為1S
private static final long CALL_TIME_UPDATE_INTERVAL_MS = 1000;
//我們需要獲取一些全局的變量,已到達不停的創(chuàng)建notification并更新同一個notification的UI
private CallTimer mCallTimer;
private Notification.Builder mCopyBuilder;
private int mCopyCallState;
private ContactCacheEntry mCopyContactInfo;
private int mCopyNotificationType; //當前notification的ID,通過這個ID我們可以一直更新同一個notification并且只會彈出一次
private Bitmap mCopyLargeIcon;
public StatusBarNotifier(Context context, ContactInfoCache contactInfoCache) {
.......省略部分代碼
//StatusBarNotifier初始化的時候就創(chuàng)建CallTimer對象,用來計算時間和更新UI
mCallTimer = new CallTimer(new Runnable() {
@Override
public void run() {
updateCallTime(); //更新UI的函數(shù)
}
});
}
@Override
public void onStateChange(InCallState oldState, InCallState newState, CallList callList) {
if (callList.getActiveCall() == null || callList.getActiveCall().getState() != Call.State.ACTIVE){
//當通話結(jié)束時需要取消計算時間的線程
mCallTimer.cancel();
}
}
//系統(tǒng)構(gòu)建notification的方法
private void buildAndSendNotification(Call originalCall, ContactCacheEntry contactInfo) {
....省略部分代碼
else if (callState == Call.State.ACTIVE && !mIsCallUiShown) {
//保存一個公共的變量到全部變量里面,方便后面構(gòu)造新的notification并刷新
copyInfoFromHeadsUpView(builder, callState, contactInfo, notificationType, largeIcon);
//下面是計算顯示的時間
final long callStart = call.getConnectTimeMillis();
final long duration = System.currentTimeMillis() - callStart;
//創(chuàng)建一個HeadsUpView顯示在notification上面
RemoteViews inCall = createInCallHeadsUpView(duration / 1000, largeIcon);
builder.setContent(inCall);
builder.setCustomHeadsUpContentView(inCall);
//系統(tǒng)原生的方法最后notify通知
fireNotification(builder, callState, contactInfo, notificationType);
//開始我們的計時線程
mCallTimer.start(CALL_TIME_UPDATE_INTERVAL_MS);
}
.....省略部分代碼
}
private RemoteViews createInCallHeadsUpView(Long callDuration, Bitmap contactAvatar) {
RemoteViews headsUpView = new RemoteViews(mContext.getPackageName(), R.layout.in_call_headsup);
if (null != contactAvatar) {
headsUpView.setImageViewBitmap(R.id.in_call_hu_avatar, contactAvatar);
}
//格式化時間
String callTimeElapsed = DateUtils.formatElapsedTime(callDuration);
headsUpView.setTextViewText(R.id.in_call_hu_elapsedTime, callTimeElapsed);
return headsUpView;
}
/*according the mCallTimer to update time data*/
public void updateCallTime() {
Call call = CallList.getInstance().getActiveCall();
final long callStart = call.getConnectTimeMillis();
final long duration = System.currentTimeMillis() - callStart;
RemoteViews inCall = createInCallHeadsUpView(duration / 1000, mCopyLargeIcon);
mCopyBuilder.setContent(inCall);
mCopyBuilder.setCustomHeadsUpContentView(inCall);
Notification notification = mCopyBuilder.build();
notification.vibrate = IN_CALL_VIBRATE_PATTERN_NULL;
mNotificationManager.notify(mCopyNotificationType, notification);
}
/*Change local variables to global variables*/
private void copyInfoFromHeadsUpView(Notification.Builder builder, int callState, ContactCacheEntry contactInfo,
int notificationType, Bitmap largeIcon){
mCopyBuilder = builder;
mCopyCallState = callState;
mCopyContactInfo = contactInfo;
mCopyNotificationType = notificationType;
mCopyLargeIcon = largeIcon;
}
........省略部分代碼
CallTimer源碼如下
package com.android.incallui;
import com.google.common.base.Preconditions;
import android.os.Handler;
import android.os.SystemClock;
/**
* Helper class used to keep track of events requiring regular intervals.
*/
public class CallTimer extends Handler {
private Runnable mInternalCallback;
private Runnable mCallback;
private long mLastReportedTime;
private long mInterval;
private boolean mRunning;
public CallTimer(Runnable callback) {
Preconditions.checkNotNull(callback);
mInterval = 0;
mLastReportedTime = 0;
mRunning = false;
mCallback = callback;
mInternalCallback = new CallTimerCallback();
}
public boolean start(long interval) {
if (interval <= 0) {
return false;
}
// cancel any previous timer
cancel();
mInterval = interval;
mLastReportedTime = SystemClock.uptimeMillis();
mRunning = true;
periodicUpdateTimer();
return true;
}
public void cancel() {
removeCallbacks(mInternalCallback);
mRunning = false;
}
private void periodicUpdateTimer() {
if (!mRunning) {
return;
}
final long now = SystemClock.uptimeMillis();
long nextReport = mLastReportedTime + mInterval;
while (now >= nextReport) {
nextReport += mInterval;
}
postAtTime(mInternalCallback, nextReport);
mLastReportedTime = nextReport;
// Run the callback
mCallback.run();
}
private class CallTimerCallback implements Runnable {
@Override
public void run() {
periodicUpdateTimer();
}
}
}
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android開發(fā)服務(wù)Service全面講解
Android的服務(wù)是開發(fā)Android應(yīng)用程序的重要組成部分。不同于活動Activity,服務(wù)是在后臺運行,服務(wù)沒有接口,生命周期也與活動Activity非常不同。通過使用服務(wù)我們可以實現(xiàn)一些后臺操作,比如想從遠程服務(wù)器加載一個網(wǎng)頁等,下面來看看詳細內(nèi)容,需要的朋友可以參考下2023-02-02
Android中post請求傳遞json數(shù)據(jù)給服務(wù)端的實例
下面小編就為大家分享一篇Android中post請求傳遞json數(shù)據(jù)給服務(wù)端的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-01-01
Android從系統(tǒng)Gallery獲取圖片具體實現(xiàn)
這篇文章主要介紹了Android從系統(tǒng)Gallery獲取圖片具體實現(xiàn),有需要的朋友可以參考一下2013-12-12
Android應(yīng)用開發(fā)中模擬按下HOME鍵的效果(實現(xiàn)代碼)
Android應(yīng)用開發(fā)中, 有一種場景,就是我們不希望用戶直接按Back鍵退出Activity,而是希望應(yīng)用隱藏到后臺,類似于按Home鍵的效果2013-05-05

