diff --git a/plugin.xml b/plugin.xml
index 377da74..495ac31 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -24,6 +24,11 @@
+
+
+
+
+
@@ -37,7 +42,9 @@
/>
+ android:exported="true"
+ android:foregroundServiceType="phoneCall"
+ >
diff --git a/src/android/CallActionReceiver.java b/src/android/CallActionReceiver.java
index 318b673..870eab1 100644
--- a/src/android/CallActionReceiver.java
+++ b/src/android/CallActionReceiver.java
@@ -23,21 +23,11 @@ public void onReceive(Context context, Intent intent) {
conn.onReject();
} else if (action.equals("answerCall")) {
conn.onAnswer();
- } else if (action.equals("hangUpCall")) {
- conn.onDisconnect();
} else {
throw new RuntimeException("Invalid action: " + action);
}
} else {
Log.d(TAG, "Exiting, connection no longer exists. pushMessagePayload: " + pushMessagePayload);
- if (intent.hasExtra("notificationID")) {
- // For safety ensure any associated notification is closed (avoids bad UX if the normal logic
- // that closes the notification when the connection is disconnected fails/crashes/etc.)
- int notificationID = intent.getIntExtra("notificationID", 0);
- Log.e(TAG, "Closing orphaned notification, ID: " + notificationID);
- NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
- nm.cancel(notificationID);
- }
}
}
}
diff --git a/src/android/CallNotification.java b/src/android/CallNotification.java
index aa5779a..21676be 100644
--- a/src/android/CallNotification.java
+++ b/src/android/CallNotification.java
@@ -1,5 +1,6 @@
package com.dmarc.cordovacall;
+import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -10,9 +11,6 @@
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
-import android.os.Handler;
-import android.telecom.Connection;
-import android.telecom.DisconnectCause;
import android.util.Log;
import androidx.core.app.NotificationCompat;
@@ -20,7 +18,6 @@
import org.json.JSONException;
import org.json.JSONObject;
-import java.net.URI;
import java.util.Random;
@@ -31,8 +28,6 @@ public class CallNotification {
private Integer notificationID;
private Context context;
private NotificationManager notificationManager;
- private Runnable timeoutRunnable;
- private Handler timeoutHandler = new Handler();
private static final String NOTIFICATION_CHANNEL_ID = "incoming_calls";
@@ -50,11 +45,11 @@ public CallNotification(String pushMessagePayload, Context context) {
this.createNotificationChannel();
}
- public void show(Style style) {
+ public Notification build(Style style) {
this.show(style, NotificationCompat.PRIORITY_HIGH);
}
- public void show(Style style, int priority) {
+ public Notification build(Style style, int priority) {
int timeout = 30000;
// NOTE: "Notifications should only launch a BroadcastReceiver from notification actions"
@@ -171,31 +166,13 @@ public void show(Style style, int priority) {
}
Log.d(TAG, "launching call notification via android NotificationManager notify()...");
- notificationManager.notify(this.notificationID, builder.build());
+ Notification notification = builder.build();
- if (this.timeoutRunnable != null) {
- this.timeoutHandler.removeCallbacks(this.timeoutRunnable);
- }
-
- this.timeoutRunnable = new Runnable() {
- @Override
- public void run() {
- Log.d(TAG, "call missed, closing connection and call notification,");
- Connection conn = MyConnectionService.getConnectionByPayload(pushMessagePayload);
- conn.setDisconnected(new DisconnectCause(DisconnectCause.MISSED));
- close();
- }
- };
-
- this.timeoutHandler.postDelayed(timeoutRunnable, timeout);
+ return notification;
}
- public void close() {
- Log.d(TAG, "closing call notification");
- this.notificationManager.cancel(this.notificationID);
- if (this.timeoutRunnable != null) {
- this.timeoutHandler.removeCallbacks(this.timeoutRunnable);
- }
+ public int getNotificationID() {
+ return this.notificationID;
}
private Uri getRingtoneURI() {
diff --git a/src/android/MyConnectionService.java b/src/android/MyConnectionService.java
index 5b639b7..5a52a8d 100644
--- a/src/android/MyConnectionService.java
+++ b/src/android/MyConnectionService.java
@@ -1,14 +1,18 @@
package com.dmarc.cordovacall;
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL;
+
import org.apache.cordova.PluginResult;
import org.json.JSONException;
import org.json.JSONObject;
+import android.app.Notification;
import android.content.Intent;
import android.content.Context;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.graphics.drawable.Icon;
+import android.os.Build;
import android.os.Bundle;
import android.telecom.Connection;
import android.telecom.ConnectionRequest;
@@ -221,7 +225,9 @@ public void run() {
CordovaCall.registerMainActivityStateChangeListener(this.mainActivityChangeListener);
this.callNotification = new CallNotification(payloadString, context);
- this.callNotification.show(CallNotification.Style.INCOMING_CALL);
+ Notification notification = this.callNotification.build(CallNotification.Style.INCOMING_CALL);
+
+ startForeground(this.callNotification.getNotificationID(), notification, FOREGROUND_SERVICE_TYPE_PHONE_CALL);
}
private void updateNotification() {
@@ -234,14 +240,10 @@ private void updateNotification() {
int priority = (style == CallNotification.Style.ONGOING_CALL && isInForeground) ? NotificationCompat.PRIORITY_MIN : NotificationCompat.PRIORITY_HIGH;
Log.d(TAG, "updating notification style: " + style + " priority: " + priority);
- this.callNotification.show(style, priority);
- }
+ Notification notification = this.callNotification.build(style, priority);
- private void closeNotification() {
- if (this.callNotification != null) {
- this.callNotification.close();
- this.callNotification = null;
- }
+ // Call startForeground again which allows for updating the associated notification of the same ID
+ startForeground(this.callNotification.getNotificationID(), notification, FOREGROUND_SERVICE_TYPE_PHONE_CALL);
}
@Override
@@ -251,7 +253,6 @@ public void onAnswer() {
activeConnectionUUID = callUUID;
showWebApp("answerCall", payloadString);
-
CordovaCall.emitEvent("answer", new PluginResult(PluginResult.Status.OK, payloadString));
}
@@ -288,7 +289,7 @@ public void onStateChanged(int state) {
updateNotification(); // Will update it to an "ongoing" CallStyle notification
break;
case Connection.STATE_DISCONNECTED:
- this.closeNotification();
+ stopForeground(STOP_FOREGROUND_REMOVE); // Cancels the associated notification
connectionMap.remove(callUUID);
if (activeConnectionUUID != null && activeConnectionUUID.equals(callUUID)) {
activeConnectionUUID = null;