Android Notification realizes dynamic display of talk time
- 2021-12-19 06:56:00
- OfStack
Based on android N MTK release source code, for your reference, the specific contents are as follows
This article mainly explains how to constantly update the notification of IncallUI to show how long it has been talking at present, so as to achieve 1 talk time on the incallUI talk interface.
Main ideas
1. We need to know when the call is set up, that is, when the state of call changes from INCOMING or DIALING to ACTIVE
2. Time will change every second, so we need to constantly update the interface of notification. We are constantly creating an notification with notify, which has reached the effect of updating time
3. We need CallTimer thread to help us calculate the time and control the update of the interface
Code implementation
This is in the source code incallUI directory StatusBarNotifier. java modification
.... Omit part of the code
// Vibration duration, here is no vibration
private static final long[] IN_CALL_VIBRATE_PATTERN_NULL = new long[] {0, 0, 0};
// How often do threads execute 1 Sub-already ms Is the unit, where it is 1S
private static final long CALL_TIME_UPDATE_INTERVAL_MS = 1000;
// We need to get 1 Some global variables have been created without stopping notification And update the same as 1 A notification Adj. UI
private CallTimer mCallTimer;
private Notification.Builder mCopyBuilder;
private int mCopyCallState;
private ContactCacheEntry mCopyContactInfo;
private int mCopyNotificationType; // Current notification Adj. ID, Through this ID We can 1 Direct update with 1 A notification And will only pop up 1 Times
private Bitmap mCopyLargeIcon;
public StatusBarNotifier(Context context, ContactInfoCache contactInfoCache) {
....... Omit part of the code
//StatusBarNotifier Create when initializing CallTimer Object used to calculate time and update UI
mCallTimer = new CallTimer(new Runnable() {
@Override
public void run() {
updateCallTime(); // Update UI Function of
}
});
}
@Override
public void onStateChange(InCallState oldState, InCallState newState, CallList callList) {
if (callList.getActiveCall() == null || callList.getActiveCall().getState() != Call.State.ACTIVE){
// Need to cancel the thread that calculates the time when the call ends
mCallTimer.cancel();
}
}
// System construction notification Method of
private void buildAndSendNotification(Call originalCall, ContactCacheEntry contactInfo) {
.... Omit part of the code
else if (callState == Call.State.ACTIVE && !mIsCallUiShown) {
// Save 1 Common variables into all variables, which is convenient to construct new ones later notification And refresh
copyInfoFromHeadsUpView(builder, callState, contactInfo, notificationType, largeIcon);
// The following is the time displayed by calculation
final long callStart = call.getConnectTimeMillis();
final long duration = System.currentTimeMillis() - callStart;
// Create 1 A HeadsUpView Display in notification Above
RemoteViews inCall = createInCallHeadsUpView(duration / 1000, largeIcon);
builder.setContent(inCall);
builder.setCustomHeadsUpContentView(inCall);
// The system native method finally notify Notice
fireNotification(builder, callState, contactInfo, notificationType);
// Start our timing thread
mCallTimer.start(CALL_TIME_UPDATE_INTERVAL_MS);
}
..... Omit part of the code
}
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);
}
// Formatting time
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;
}
........ Omit part of the code
The source code of CallTimer is as follows
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();
}
}
}