Skip to content

Commit

Permalink
draft
Browse files Browse the repository at this point in the history
  • Loading branch information
fabriziomoscon committed Nov 13, 2020
1 parent 64c59fa commit 7e6d794
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 41 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package com.hoxfon.react.RNTwilioVoice;

import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

import com.facebook.react.HeadlessJsTaskService;

import java.util.List;
//import java.util.Random;
//
//import androidx.localbroadcastmanager.content.LocalBroadcastManager;
//
//import com.facebook.react.ReactApplication;
//import com.facebook.react.ReactInstanceManager;
//import com.facebook.react.bridge.ReactApplicationContext;
//import com.facebook.react.bridge.ReactContext;
//import com.hoxfon.react.RNTwilioVoice.CallNotificationManager;
//
//import static com.hoxfon.react.RNTwilioVoice.TwilioVoiceModule.ACTION_INCOMING_CALL;
//import static com.hoxfon.react.RNTwilioVoice.TwilioVoiceModule.INCOMING_CALL_INVITE;
//import static com.hoxfon.react.RNTwilioVoice.TwilioVoiceModule.INCOMING_CALL_NOTIFICATION_ID;
import static com.hoxfon.react.RNTwilioVoice.TwilioVoiceModule.TAG;

public class BackgroundCallReceiver extends BroadcastReceiver {

@Override
public void onReceive(final Context context, final Intent intent) {
Log.d(TAG, "### onReceive");
/**
This part will be called every time network connection is changed
e.g. Connected -> Not Connected
**/
if (!isAppOnForeground((context))) {
// ReactApplicationContext ctx = new ReactApplicationContext(context);
//
// Random randomNumberGenerator = new Random(System.currentTimeMillis());
// final int notificationId = randomNumberGenerator.nextInt();
// CallNotificationManager callNotificationManager = new CallNotificationManager();
//
// int appImportance = callNotificationManager.getApplicationImportance(ctx);
// if (BuildConfig.DEBUG) {
// Log.d(TAG, "CONTEXT not present appImportance = " + appImportance);
// }
// Intent launchIntent = callNotificationManager.getLaunchIntent(
// ctx,
// notificationId,
// intent.getStringExtra("call_sid"),
// intent.getStringExtra("call_from"),
// intent.getStringExtra("call_to"),
// true,
// ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND
// );
// context.startActivity(launchIntent);
//// Intent callInviteIntent = new Intent(ACTION_INCOMING_CALL);
//// callInviteIntent.putExtra(INCOMING_CALL_NOTIFICATION_ID, notificationId);
//// LocalBroadcastManager.getInstance(context).sendBroadcast(callInviteIntent);
//// callNotificationManager.createIncomingCallNotification(
//// ctx,
//// intent.getStringExtra("call_sid"),
//// intent.getStringExtra("call_from"),
//// notificationId,
//// launchIntent
//// );



/**
We will start our service and send extra info about
network connections
**/
Bundle extras = intent.getExtras();
Intent serviceIntent = new Intent(context, BackgroundCallTaskService.class);
serviceIntent.putExtras(extras);
context.startService(serviceIntent);
HeadlessJsTaskService.acquireWakeLockNow(context);
}
}

private boolean isAppOnForeground(Context context) {
/**
We need to check if app is in foreground otherwise the app will crash.
http://stackoverflow.com/questions/8489993/check-android-application-is-in-foreground-or-not
**/
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> appProcesses =
activityManager.getRunningAppProcesses();
if (appProcesses == null) {
return false;
}
final String packageName = context.getPackageName();
for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.importance ==
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND &&
appProcess.processName.equals(packageName)) {
return true;
}
}
return false;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.hoxfon.react.RNTwilioVoice;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

import com.facebook.react.HeadlessJsTaskService;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.jstasks.HeadlessJsTaskConfig;

import static com.hoxfon.react.RNTwilioVoice.TwilioVoiceModule.TAG;

public class BackgroundCallTaskService extends HeadlessJsTaskService {
@Override
protected HeadlessJsTaskConfig getTaskConfig(Intent intent) {
Bundle extras = intent.getExtras();
Log.d(TAG, "###getTaskConfig"+ extras.toString());
if (extras != null) {
return new HeadlessJsTaskConfig(
"BackgroundCallTaskService",
Arguments.fromBundle(extras),
5000, // timeout for the task
false // optional: defines whether or not the task is allowed in foreground. Default is false
);
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ public Class getMainActivityClass(ReactApplicationContext context) {

public Intent getLaunchIntent(ReactApplicationContext context,
int notificationId,
CallInvite callInvite,
String callInviteSid,
String callInviteFrom,
String callInviteTo,
Boolean shouldStartNewTask,
int appImportance
) {
Expand All @@ -107,14 +109,15 @@ public Intent getLaunchIntent(ReactApplicationContext context,
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
);

if (callInvite != null) {
launchIntent.putExtra(INCOMING_CALL_INVITE, callInvite);
}
launchIntent.putExtra("callSid", callInviteSid);
launchIntent.putExtra("callFrom", callInviteFrom);
launchIntent.putExtra("callTo", callInviteTo);
return launchIntent;
}

public void createIncomingCallNotification(ReactApplicationContext context,
CallInvite callInvite,
String callInviteSid,
String callInviteFrom,
int notificationId,
Intent launchIntent)
{
Expand All @@ -131,7 +134,7 @@ public void createIncomingCallNotification(ReactApplicationContext context,
*/
Bundle extras = new Bundle();
extras.putInt(INCOMING_CALL_NOTIFICATION_ID, notificationId);
extras.putString(CALL_SID_KEY, callInvite.getCallSid());
extras.putString(CALL_SID_KEY, callInviteSid);
extras.putString(NOTIFICATION_TYPE, ACTION_INCOMING_CALL);
/*
* Create the notification shown in the notification drawer
Expand All @@ -145,7 +148,7 @@ public void createIncomingCallNotification(ReactApplicationContext context,
.setCategory(NotificationCompat.CATEGORY_CALL)
.setSmallIcon(R.drawable.ic_call_white_24dp)
.setContentTitle("Incoming call")
.setContentText(callInvite.getFrom() + " is calling")
.setContentText(callInviteFrom + " is calling")
.setOngoing(true)
.setAutoCancel(true)
.setExtras(extras)
Expand Down Expand Up @@ -180,7 +183,7 @@ public void createIncomingCallNotification(ReactApplicationContext context,
notificationBuilder.addAction(R.drawable.ic_call_white_24dp, "ANSWER", pendingAnswerIntent);

notificationManager.notify(notificationId, notificationBuilder.build());
TwilioVoiceModule.callNotificationMap.put(INCOMING_NOTIFICATION_PREFIX+callInvite.getCallSid(), notificationId);
TwilioVoiceModule.callNotificationMap.put(INCOMING_NOTIFICATION_PREFIX+callInviteSid, notificationId);
}

public void initCallNotificationsChannel(NotificationManager notificationManager) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -461,8 +461,7 @@ private void handleIncomingCallIntent(Intent intent) {
if (BuildConfig.DEBUG) {
Log.d(TAG, "handleIncomingCallIntent");
}
activeCallInvite = intent.getParcelableExtra(INCOMING_CALL_INVITE);
if (activeCallInvite != null) {
if (intent != null) {
callAccepted = false;
SoundPoolManager.getInstance(getReactApplicationContext()).playRinging();

Expand All @@ -479,9 +478,9 @@ private void handleIncomingCallIntent(Intent intent) {
appImportance == RunningAppProcessInfo.IMPORTANCE_SERVICE) {

WritableMap params = Arguments.createMap();
params.putString("call_sid", activeCallInvite.getCallSid());
params.putString("call_from", activeCallInvite.getFrom());
params.putString("call_to", activeCallInvite.getTo()); // TODO check if needed
params.putString("call_sid", intent.getStringExtra("callSid"));
params.putString("call_from", intent.getStringExtra("callFrom"));
params.putString("call_to", intent.getStringExtra("callTo"));
eventManager.sendEvent(EVENT_DEVICE_DID_RECEIVE_INCOMING, params);
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import android.app.ActivityManager;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
Expand Down Expand Up @@ -60,7 +61,7 @@ public void onNewToken(String token) {
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
if (BuildConfig.DEBUG) {
Log.d(TAG, "Bundle data: " + remoteMessage.getData());
Log.d(TAG, "VoiceFirebaseMessagingService onMessageReceived: " + remoteMessage.getMessageType());
}

// Check if message contains a data payload.
Expand All @@ -74,7 +75,6 @@ public void onMessageReceived(RemoteMessage remoteMessage) {
boolean valid = Voice.handleMessage(data, new MessageListener() {
@Override
public void onCallInvite(final CallInvite callInvite) {

// We need to run this on the main thread, as the React code assumes that is true.
// Namely, DevServerHelper constructs a Handler() without a Looper, which triggers:
// "Can't create handler inside thread that has not called Looper.prepare()"
Expand All @@ -93,7 +93,9 @@ public void run() {
Intent launchIntent = callNotificationManager.getLaunchIntent(
(ReactApplicationContext)context,
notificationId,
callInvite,
callInvite.getCallSid(),
callInvite.getFrom(),
callInvite.getTo(),
false,
appImportance
);
Expand All @@ -106,28 +108,53 @@ public void run() {
intent.putExtra(INCOMING_CALL_INVITE, callInvite);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
} else {
// Otherwise wait for construction, then handle the incoming call
mReactInstanceManager.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() {
public void onReactContextInitialized(ReactContext context) {
int appImportance = callNotificationManager.getApplicationImportance((ReactApplicationContext)context);
if (BuildConfig.DEBUG) {
Log.d(TAG, "CONTEXT not present appImportance = " + appImportance);
}
Intent launchIntent = callNotificationManager.getLaunchIntent((ReactApplicationContext)context, notificationId, callInvite, true, appImportance);
context.startActivity(launchIntent);
Intent intent = new Intent(ACTION_INCOMING_CALL);
intent.putExtra(INCOMING_CALL_NOTIFICATION_ID, notificationId);
intent.putExtra(INCOMING_CALL_INVITE, callInvite);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
callNotificationManager.createIncomingCallNotification(
(ReactApplicationContext) context, callInvite, notificationId,
launchIntent);
}
});
if (!mReactInstanceManager.hasStartedCreatingInitialContext()) {
// Construct it in the background
mReactInstanceManager.createReactContextInBackground();
}
Intent callKeepIntent = new Intent();
callKeepIntent.setAction("com.hoxfon.HoxFon.DEV.debug.BACKGROUND_CALL");
callKeepIntent.setPackage("com.hoxfon.HoxFon.DEV.debug");
Bundle bundle = new Bundle();
bundle.putString("call_state", "PENDING");
bundle.putString("call_sid", callInvite.getCallSid());
bundle.putString("call_from", callInvite.getFrom());
bundle.putString("call_to", callInvite.getTo());
callKeepIntent.putExtras(bundle);
Log.d(TAG, "BACKGROUND onCallInvite, callKeepIntent "+ callKeepIntent);

sendBroadcast(callKeepIntent);

// // Otherwise wait for construction, then handle the incoming call
// mReactInstanceManager.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() {
// public void onReactContextInitialized(ReactContext context) {
// int appImportance = callNotificationManager.getApplicationImportance((ReactApplicationContext)context);
// if (BuildConfig.DEBUG) {
// Log.d(TAG, "CONTEXT not present appImportance = " + appImportance);
// }
// Intent launchIntent = callNotificationManager.getLaunchIntent(
// (ReactApplicationContext)context,
// notificationId,
// callInvite.getCallSid(),
// callInvite.getFrom(),
// callInvite.getTo(),
// true,
// appImportance
// );
// context.startActivity(launchIntent);
// Intent intent = new Intent(ACTION_INCOMING_CALL);
// intent.putExtra(INCOMING_CALL_NOTIFICATION_ID, notificationId);
// intent.putExtra(INCOMING_CALL_INVITE, callInvite);
// LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
// callNotificationManager.createIncomingCallNotification(
// (ReactApplicationContext) context,
// callInvite.getCallSid(),
// callInvite.getFrom(),
// notificationId,
// launchIntent
// );
// }
// });
// if (!mReactInstanceManager.hasStartedCreatingInitialContext()) {
// // Construct it in the background
// mReactInstanceManager.createReactContextInBackground();
// }
}
}
});
Expand Down Expand Up @@ -160,8 +187,19 @@ public void run() {
*/
private void sendCancelledCallInviteToActivity(CancelledCallInvite cancelledCallInvite) {
SoundPoolManager.getInstance((this)).stopRinging();
Intent intent = new Intent(ACTION_CANCEL_CALL_INVITE);
intent.putExtra(CANCELLED_CALL_INVITE, cancelledCallInvite);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
// Intent intent = new Intent(ACTION_CANCEL_CALL_INVITE);
// intent.putExtra(CANCELLED_CALL_INVITE, cancelledCallInvite);
// LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

Intent callKeepIntent = new Intent();
callKeepIntent.setAction("com.hoxfon.react.RNTwilioVoice.BACKGROUND_CALL");
callKeepIntent.setPackage("com.hoxfon.react.RNTwilioVoice");
Bundle bundle = new Bundle();
bundle.putString("call_state", "CANCELLED");
bundle.putString("call_sid", cancelledCallInvite.getCallSid());
bundle.putString("call_from", cancelledCallInvite.getFrom());
bundle.putString("call_to", cancelledCallInvite.getTo());
callKeepIntent.putExtras(bundle);
sendBroadcast(callKeepIntent);
}
}

0 comments on commit 7e6d794

Please sign in to comment.