androidvideotwiliocallvoip-android

Android Twilio Video Call, wake up app and bring to foreground


I am trying to provide a native video calling experience with Twilio Video Call. Here is the scenario:

  1. Person AAA calls person BBB.
  2. Person BBB does not have the app open, in the background or foreground, app is in killed state, phone may even be locked.
  3. When a call from AAA arrives, the app is opened with a video ui with an answer button. Just like in WhatsApp, Google Duo, Skype...

We have FCM in place and are receiving a push notification. Trying to open the video call answer button the moment the call arrives, without clicking the notification, just like in Whatsapp, Google Duo... (in Android phones)

We tried to have a Service running in the background with a socket open in it. The socket would listen to incoming calls and open the VideoCallActivity when an incoming call event is emitted to the socket.

This was our best bet but no success so far. How would you achieve this functionality?


Solution

  • So we had figured out this solution (when a notification arrives, bring the app to foreground) and I'm posting it even though it's been a while:

    1. The FCM notification (firebase cloud messaging notification) needs to only send "data" in the notification. So no Notification object in the JSON structure of the notification, only data. This way the notification is handled by your app's FirebaseMessagingService.java class. Please read the below in detail to understand how 2 FCM notification types are handled. https://firebase.google.com/docs/cloud-messaging/android/receive https://firebase.google.com/docs/cloud-messaging/concept-options#notifications_and_data_messages

    2. In the FirebaseMessagingService.java class, launch a VideoCall activity with an Intent. Don't forget to add this service to the Manifest.xml

               Intent intent = new Intent(this, VideoCallActivity.class);
               intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
               intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
               getApplicationContext().startActivity(intent);
      
    3. In the VideoCall activity, make sure you have the below code at the beginning of onCreate() :

       // These flags ensure that the activity can be launched when the screen is locked.
       Window window = getWindow();
       window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
               | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
               | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
      
       // to wake up the screen
       PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
       PowerManager.WakeLock wakeLock = pm.newWakeLock((PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "TAG");
       wakeLock.acquire();
      
       // to release the screen lock
       KeyguardManager keyguardManager = (KeyguardManager) getApplicationContext().getSystemService(Context.KEYGUARD_SERVICE);
       KeyguardManager.KeyguardLock keyguardLock = keyguardManager.newKeyguardLock("TAG");
       keyguardLock.disableKeyguard();
      
    4. Add the VideoCallActivity to the Manifest.xml with the appropriate intent-filter:

      <!-- Video Call -->
      <activity
          android:name=".ui.activities.video_call.VideoCallActivity"
          android:launchMode="singleTop"
          android:screenOrientation="portrait"
          android:theme="@style/AppTheme.NoActionBar">
          <intent-filter>
              <!-- Note: these actions are notification actions -->
              <action android:name="VIDEO_CALLING" />
              <category android:name="android.intent.category.DEFAULT" />
          </intent-filter>
      </activity>
      
      

    Optional: To make the phone ring and vibrate:

    // For Incoming Call
    // 1. declare
    private MediaPlayer incomingCallMediaPlayer;
    // .2 in onCreate, if I'm the person that's calling, ring the phone 
    incomingCallMediaPlayer = MediaPlayer.create(this, R.raw.incoming);
    incomingCallMediaPlayer.setLooping(true);
    incomingCallMediaPlayer.start();
    // 3. when I pick up, stop the player
    incomingCallMediaPlayer.stop();
    
    // I play R.raw.incoming if I'm being called.
    // I play R.raw.outgoing when I'm calling.
    // I understand if I'm the one calling from the number of participants in the "room" (this is a video call terminology) and bypassing in a variable through the intent
    
    // For Outgoing Call
    // 1. declare
    private MediaPlayer callingMediaPlayer;
    
    // 2. in onCreate, if I'm being called, ring the phone
    callingMediaPlayer = MediaPlayer.create(this, R.raw.outgoing);
    callingMediaPlayer.setLooping(true);
    callingMediaPlayer.start();
    
    // 3. when another "participant" (this is a video call terminology) joins the "room" I stop playing the sound
    callingMediaPlayer.stop();
    
    // to Vibrate, add the code with the media players and stop vibrate with media players
    //https://stackoverflow.com/questions/13950338/how-to-make-an-android-device-vibrate