SoFunction
Updated on 2025-04-08

Android uses message push to achieve similar WeChat video answering

This article shares the specific code of Android's implementation of WeChat video answering for your reference. The specific content is as follows

1. Background requirements:The service needs to access the video audit function, initiate a video call on the PC side, and click to answer the call interface on the mobile side to perform a 1-to-1 video call.

2. Solution:Because the project does not have IM function. Only integrated Aurora message push (Aurora message push access referenceOfficial Documentation, after communicating with the needs, the call answering interface is activated using message push. Integrate Tencent real-time audio and video SDK (refer to the specific integration methodOfficial Documentation). Finally, a 1-to-1 call function similar to WeChat is implemented.

3. Technology implementation:

A: Write a broadcast receiver and register it in AndroidManifest, which is a global broadcast receiver. The application retreats to the background or the application process is killed. As long as the Aurora push process is Live, it can receive messages and start the call answering interface.

/**
  * Created on 2018/3/29 16:19
  * @author
  * Aurora Push Broadcast Receiver
  */
public class JiGuangPushReceiver extends BroadcastReceiver {
  private static final String TAG = "JPushReceiver";
  @Override
  public void onReceive(Context context, Intent intent) {
    Bundle bundle = ();
    if (bundle == null) {
      return;
    }
    //Get the lock screen manager    KeyguardManager km = (KeyguardManager) (Context.KEYGUARD_SERVICE);
    if (km != null && ()) {  //If true, it is locked.      startLoginOrCallActivity(context,bundle);
    } else {
      if (JPushInterface.ACTION_REGISTRATION_ID.equals(())) {
        String regId = (JPushInterface.EXTRA_REGISTRATION_ID);
        (TAG, "[MyReceiver] Receive Registration Id: " + regId);
        //send the Registration Id to yours server...
      } else if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(())) {
        (TAG, "[MyReceiver] Received the pushed custom message: " + (JPushInterface.EXTRA_MESSAGE));
      } else if (JPushInterface.ACTION_NOTIFICATION_RECEIVED.equals(())) {//Received the push notification        //Start the call interface        startLoginOrCallActivity(context, bundle);
      } else if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(())) {//Click the notification bar        //Start the call interface        startLoginOrCallActivity(context, bundle);
        //Clear notifications of all status        (context);
      } else if (JPushInterface.ACTION_RICHPUSH_CALLBACK.equals(())) {
        (TAG, "[MyReceiver] The user received RICH PUSH CALLBACK: " + (JPushInterface.EXTRA_EXTRA));
        //Here, according to the content processing code of JPushInterface.EXTRA_EXTRA, such as opening a new activity, opening a web page, etc.      }
    }
  }

  /**
    * Not logged in and jump to the login interface,
    * else start the call answering interface
    */
  private void startLoginOrCallActivity(Context context, Bundle bundle) {
    //EXTRA_EXTRA
    String extras = (JPushInterface.EXTRA_EXTRA);
    String userID = (context, Constants.LOGIN_USER_ID);
    if ((userID)) {
      //Start the login interface      Intent intent = new Intent(context, );
      (Intent.FLAG_ACTIVITY_NEW_TASK);
      (intent);
    } else {
      //Start the call answering interface      int notifyId = (JPushInterface.EXTRA_NOTIFICATION_ID);
      if (!(extras) && ("androidNotification extras key")){
        (context, extras,notifyId);
      }
    }
  }
 }
//Register global custom broadcast receiver in AndroidManifest<receiver
      android:name=".`Insert the code chip `ushReceiver" here
      android:enabled="true"
      android:exported="false">
      <intent-filter>
        <action android:name="" /> <!-- Required User registrationSDKofintent -->
        <action android:name=".MESSAGE_RECEIVED" /> <!-- Required User ReceivedSDK消息ofintent -->
        <action android:name=".NOTIFICATION_RECEIVED" /> <!-- Required User ReceivedSDK通知栏信息ofintent -->
        <action android:name=".NOTIFICATION_OPENED" /> <!-- Required 用户打开自定义通知栏ofintent -->
        <action android:name="" /> <!-- Receive network changes connect/disconnect since 1.6.3 -->
        <category android:name="${PACKAGE_NAME}" />
      </intent-filter>
    </receiver>

B: Start the call answering interface, and then get the current mobile phone mode after starting the answering interface.

AudioManager audio = (AudioManager) (Context.AUDIO_SERVICE);
//Mobile phone mode, vibration, elite, ringing, and vibration or ringing modes, please refer to the following implementation code.//Click the answer button and jump to Tencent video call interface
/**
  * Created on 2019/4/28 16:19
  * @author
  * Video pre-review answering interface
  */
public class ReceiveTalkActivity extends BaseActivity {

  private static String PUSH_MSG_KEY = "push_msg_key";

  private static String NOTIFICATION_ID_KEY = "notification_id_key";

  /**
    * Tencent Cloud registered and allocated appId
    */
  private int sdkAppId =

  /**
    * Check runtime permissions
    */
  private boolean mCheckPermissionResult = false;

  private PushMsgBean mPushMsgBean;
  /**
    * Media playback
    */
  private MediaPlayer mMediaPlayer;

  /**
    * Vibration
    */
  private Vibrator mVibrator;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    Window window = getWindow();
    //Suspended window    (window,this);
    (savedInstanceState);

    //Initialize the countdown timer    initCountDownTimer();
    //Request permission    requestMustPermission();
    initViews();
    //Clear the notification corresponding to the status bar according to the notification ID    (this);
    //Continuous vibration and ringing    continuedVibratorAndMediaPlayer();
  }

  /**
    * Close activity after 60 seconds
    */
  private void initCountDownTimer() {
    long time = 30000;
    long countDownInterval = 1000;
    CountDownTimer downTimer = new CountDownTimer(time, countDownInterval) {
      @Override
      public void onTick(long millisUntilFinished) {
      }

      @Override
      public void onFinish() {
        finish();
      }
    };
    ();
  }

  @Override
  protected int getLayoutId() {
    return .activity_receive_talk;
  }

  @Override
  protected boolean initToolbar() {
    return false;
  }

  @Override
  protected void getIntent(Intent intent) {
    String pushMsg = getIntent().getStringExtra(PUSH_MSG_KEY);
    //notificationId = getIntent().getIntExtra(NOTIFICATION_ID_KEY, 0);
    parsePushMsg(pushMsg);
  }

  @Override
  protected void initViews() {
    Button btnCancel = findViewById(.btn_cancel_call);
    Button btnAnswer = findViewById(.btn_answer_call);

    (v ->{
      ();
      ();
      finish();
    });

    (v -> {
      ();
      ();
      if (mCheckPermissionResult) {
        Intent intent = new Intent(this, );
        ("roomId", (()));
        ("userId", ());
        ("sdkAppId", sdkAppId);
        ("userSig", ());
        startActivity(intent);
        finish();
      } else {
        ("The required permissions are denied and video auditing cannot be enabled");
      }
    });
  }

  /**
    * Continuous ringing and vibration
    */
  private void continuedVibratorAndMediaPlayer() {

    //Get media player    mMediaPlayer = new MediaPlayer();
    try {
      (this, RingtoneManager
          .getDefaultUri(RingtoneManager.TYPE_RINGTONE));//The notification sound I used here, and there are other ones, you can click in to see      ();
    } catch (IOException e) {
      ();
    }

    //Get the handle to vibration service    mVibrator = (Vibrator)this. getSystemService(VIBRATOR_SERVICE);

    //Get the current mobile phone mode    AudioManager audio = (AudioManager) (Context.AUDIO_SERVICE);
    if (audio != null) {
      switch (()) {
        case AudioManager.RINGER_MODE_SILENT://Mute          //do sth
          break;
        case AudioManager.RINGER_MODE_NORMAL://The ringing          ();
          (true); //Loop play          break;
        case AudioManager.RINGER_MODE_VIBRATE://shock          //Array parameter meaning: The first parameter is to wait for the specified time to start vibrating.          //The vibration time is the second parameter.  The parameters behind are the waiting time for vibration and vibration          //The second parameter is the number of repetitions, -1 is not repeated, and 0 is constantly vibrating          if (mVibrator != null) {
            ( new long[]{1000,1000},0);
          }
          break;
      }
    }
  }

  private void parsePushMsg(String pushMsg) {
    if (!(pushMsg)) {
      CustomerMsg customerMsg = (pushMsg, );
      String pushMsgContent = ();
      pushMsgContent = ("\\", "");
      (,"pushMsgContent="+pushMsgContent);
      mPushMsgBean = (pushMsgContent, );
    }
  }

  /**
    * Permissions required to apply for application
    */
  private void requestMustPermission() {
    (this)
        .requestCode(Constants.REQUEST_CODE_PERMISSION)
        .permission(
            .WRITE_EXTERNAL_STORAGE,
            ,
            .RECORD_AUDIO,
            .READ_EXTERNAL_STORAGE,
            ,
            .DISABLE_KEYGUARD,
            .WAKE_LOCK
        )
        .rationale((requestCode, rationale) ->
            //Request for the right to be denied again            (this)
                .setTitle(.title_dialog)
                .setMessage(.message_permission_failed)
                .setPositiveButton(, (dialog, which) -> {
                  ();
                  ();
                })
                .setNegativeButton(, (dialog, which) -> {
                  ();
                  ();
                }).show())
        .callback(new PermissionListener() {
          @Override
          public void onSucceed(int requestCode, @NonNull List<String> grantPermissions) {
            mCheckPermissionResult = true;
          }

          @Override
          public void onFailed(int requestCode, @NonNull List<String> deniedPermissions) {
            mCheckPermissionResult = false;
          }
        })
        .start();
  }

  /**
    * The interface is not destroyed, callback is made when starting this interface
    */
  @Override
  protected void onNewIntent(Intent intent) {
    (intent);
    String pushMsg = (PUSH_MSG_KEY);
    //notificationId = (NOTIFICATION_ID_KEY, 0);
    parsePushMsg(pushMsg);
  }

  /**
    * Provides the activity provided to external calls to start the answering interface
    *
    * @param cex context object
    * @param pushMsg message content
    * @param notifyId NotificationID
    */
  public static void startReceiveTalkActivity(Context cex, String pushMsg, int notifyId) {
    Intent calIntent = new Intent(cex, );
    // Carry data    (Intent.FLAG_ACTIVITY_NEW_TASK);
    (PUSH_MSG_KEY, pushMsg);
    (NOTIFICATION_ID_KEY, notifyId);
    (calIntent);
  }

  @Override
  protected void onDestroy() {
    ();
    ();
    ();
  }
}

//Register ReceiveTalkActivity, android:launchMode="singleTask"<activity android:name="."
      android:launchMode="singleTask"
      android:screenOrientation="portrait"
      />

Summarize:Time and cost issues are considered in the project. No access to IM function. The message push is unreliable, and the Aurora push process was killed, so the message could not be received. When you open the app, many notifications will pop up. This is just a simple implementation to adjust the mobile terminal to make video calls on the PC. There are many factors that have not been taken into account, so I will record it first.

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.