0

我们正在使用Sinch voip api。有一个绑定的服务从应用程序启动开始,我们初始化服务中的sinch客户端,并始终在后台运行。我尝试在通话屏幕活动中放置通知代码,因为此活动将始终显示为接受呼叫。我的目标是能够点击通知并像whatsapp一样重新打开此通话活动。通知恢复使用backpress后台进行的活动

public class CallScreenActivity extends BaseActivity { 

    static final String TAG = CallScreenActivity.class.getSimpleName(); 

    private AudioPlayer mAudioPlayer; 
    private Timer mTimer; 
    private UpdateCallDurationTask mDurationTask; 

    private String mCallId; 
    String mCaller, mReceiver; 
    String otherusername, myname; 
    private long mCallStart = 0; 

    private TextView mCallDuration; 
    private TextView mCallState; 
    private TextView mCallerName; 
    private ImageView mCallImg; 
    private String mk, mTimestamp; 
    private String mProfpic; 
    Button endCallButton; 

    Notification notification; 
    NotificationManager notificationManager; 

    private class UpdateCallDurationTask extends TimerTask { 

     @Override 
     public void run() { 
      CallScreenActivity.this.runOnUiThread(new Runnable() { 
       @Override 
       public void run() { 
        updateCallDuration(); 
       } 
      }); 
     } 
    } 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     getWindow().addFlags(
       WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON 
         + WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD 
         | +WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED 
         | +WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); 

     setContentView(R.layout.activity_callscreen); 

     mAudioPlayer = new AudioPlayer(this); 
     mCallDuration = (TextView) findViewById(R.id.callDuration); 
     mCallerName = (TextView) findViewById(R.id.remoteUser); 
     mCallState = (TextView) findViewById(R.id.callState); 
     mCallImg = (ImageView) findViewById(R.id.imgotherusr); 
     endCallButton = (Button) findViewById(R.id.hangupButton); 

     endCallButton.setOnClickListener(new OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       endCall(); 
      } 
     }); 
     mCallStart = System.currentTimeMillis(); 
     mCallId = getIntent().getStringExtra(SinchCallService.CALL_ID); 

     UserSession us = new UserSession(this); 
     mk = us.getUserKey(); 
     myname = us.getUsername(); 

     mCaller = getIntent().getStringExtra("calleruid"); 
     mReceiver = getIntent().getStringExtra("receiveruid"); 
     otherusername = getIntent().getStringExtra("otherusername"); 
     mTimestamp = getIntent().getStringExtra("timestamp"); 
     System.out.println(mCaller+"on create call screen activity ongoing call" + mReceiver + otherusername); 

     showNotification(); 

    } 

    private void showNotification() { 
     System.out.println("show notification callscreenactivity"); 
     Intent notificationIntent = new Intent(this, CallScreenActivity.class); 
     notificationIntent.setAction("ongoingcall"); 
     notificationIntent.putExtra("calleruid", mCaller); 
     notificationIntent.putExtra("receiveruid", mReceiver); 
     notificationIntent.putExtra("otherusername", otherusername); 
     notificationIntent.putExtra("timestamp", mTimestamp); 

     PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, 
       notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); 

     Intent hangupintent = new Intent(this, CallScreenActivity.class); 
     hangupintent.setAction("hangupcall"); 
     hangupintent.setAction("ongoingcall"); 
     hangupintent.putExtra("calleruid", mCaller); 
     hangupintent.putExtra("receiveruid", mReceiver); 
     hangupintent.putExtra("otherusername", otherusername); 
     hangupintent.putExtra("timestamp", mTimestamp); 
     PendingIntent phangupintent = PendingIntent.getService(this, 0, 
       hangupintent, 0); 

     notification = new NotificationCompat.Builder(this) 
       .setContentTitle("In call with " + otherusername) 
       .setContentText("Duration " + VoiceCallHelper.formatTimespan(System.currentTimeMillis() - mCallStart)) 
       .setSmallIcon(R.drawable.iconcall) 
       .setContentIntent(pendingIntent) 
       .addAction(R.drawable.ic_arrow_back, "Hangup", 
         phangupintent).build(); 
     notificationManager = 
       (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 
     notificationManager.notify(111 /* ID of notification */, notification); 

    } 

    @Override 
    public void onServiceConnected() { 

     try { 
      doStuff(); 
     } catch (NullPointerException e) { 
      //getSinchServiceInterface() in doStuff below throw null pointer error. 
     } 
    } 

    private void doStuff() { 
     final Call call = getSinchServiceInterface().getCall(mCallId); 
     if (call != null) { 
      call.addCallListener(new SinchCallListener()); 
      mCallState.setText(call.getState().toString()); 

      DBREF_USER_PROFILES.child(call.getRemoteUserId()).addListenerForSingleValueEvent(new ValueEventListener() { 
       @Override 
       public void onDataChange(DataSnapshot dataSnapshot) { 
        if (dataSnapshot.exists()) { 
         System.out.println("datasnapshot callscreenactivity otheruser" + dataSnapshot); 
         User u = User.parse(dataSnapshot); 
         mCallerName.setText(u.getName()); 
         mProfpic = u.getProfpicurl(); 
         Glide.with(CallScreenActivity.this).load(mProfpic).into(mCallImg); 

        } else { 
         mCallerName.setText(call.getHeaders().get("username")); 
         Glide.with(CallScreenActivity.this).load(R.drawable.whatsapplogo).into(mCallImg); 

        } 
       } 

       @Override 
       public void onCancelled(DatabaseError databaseError) { 

       } 
      }); 


     } else { 
      Log.e(TAG, "Started with invalid callId, aborting."); 
      finish(); 
     } 
    } 

    @Override 
    public void onPause() { 
     super.onPause(); 
     mDurationTask.cancel(); 
     mTimer.cancel(); 
    } 

    @Override 
    public void onResume() { 
     super.onResume(); 
     mTimer = new Timer(); 
     mDurationTask = new UpdateCallDurationTask(); 
     mTimer.schedule(mDurationTask, 0, 500); 

     if (getIntent() != null && getIntent().getAction() != null) { 
      switch (getIntent().getAction()) { 
       case "ongoingcall": 
        System.out.println("on resume call screen activity ongoing call" + mCaller + mReceiver + otherusername); 
        mCaller = getIntent().getStringExtra("calleruid"); 
        mReceiver = getIntent().getStringExtra("receiveruid"); 
        otherusername = getIntent().getStringExtra("otherusername"); 
        mTimestamp = getIntent().getStringExtra("timestamp"); 
        break; 
       case "hangupcall": 
        System.out.println("on resume call screen activity hangup call"); 
        mCaller = getIntent().getStringExtra("calleruid"); 
        mReceiver = getIntent().getStringExtra("receiveruid"); 
        otherusername = getIntent().getStringExtra("otherusername"); 
        mTimestamp = getIntent().getStringExtra("timestamp"); 
        endCallButton.performClick(); 
        break; 
      } 
     } 
    } 

    @Override 
    public void onBackPressed() { 
     startActivity(new Intent(CallScreenActivity.this, MainAct.class)); 
    } 

    private void endCall() { 

     if (notification != null) { 
      System.out.println("cancelling notification in endCAll callscreenactivity"); 
      notificationManager.cancel(111); 
     } 

     mAudioPlayer.stopProgressTone(); 
     Call call = getSinchServiceInterface().getCall(mCallId); 
     if (call != null) { 
      call.hangup(); 
     } 
     finish(); 
    } 

    private void updateCallDuration() { 
     if (mCallStart > 0) { 
      mCallDuration.setText(VoiceCallHelper.formatTimespan(System.currentTimeMillis() - mCallStart)); 
      showNotification(); 
     } 
    } 

    private class SinchCallListener implements CallListener { 

     @Override 
     public void onCallEnded(Call call) { 
      CallEndCause cause = call.getDetails().getEndCause(); 
      Log.d(TAG, "Call ended. Reason: " + cause.toString() + mk + mCaller); 
      if (mk != null && mCaller != null && mk.matches(mCaller)) { 
       mAudioPlayer.stopProgressTone(); 
       setVolumeControlStream(AudioManager.USE_DEFAULT_STREAM_TYPE); 
       String endMsg = "Call ended: " + call.getDetails().toString(); 
       Long gt = GetTimeStamp.Id(); 
       Toast.makeText(CallScreenActivity.this, endMsg, Toast.LENGTH_LONG).show(); 
       System.out.println(endMsg + "mtimestamp" + mTimestamp); 

       String cau; 
       String oth; 


       if (call.getDetails().getDuration() > 0) 
        cau = "completed"; 
       else 
        cau = cause.toString(); 

       CallDetails cd1 = new CallDetails(String.valueOf(call.getDetails().getDuration()), mCaller, mReceiver, cau, String.valueOf(gt), mTimestamp, mProfpic, mCallerName.getText().toString()); 
       CallDetails cd2 = new CallDetails(String.valueOf(call.getDetails().getDuration()), mCaller, mReceiver, cau, String.valueOf(gt), mTimestamp, mProfpic, myname); 
       System.out.println(mCaller + "end msg callscreenactivity" + mReceiver + " " + String.valueOf(gt)); 
       System.out.println("end msg callscreenactivity" + mReceiver + " " + DBREF.child("VoiceCalls").child(mCaller).child(String.valueOf(gt))); 

       //setting in mCaller mykey node at voicecalls node firebase 
       DBREF_CALLS.child(mCaller).child(String.valueOf(gt)).setValue(cd1); 
       //setting in mReceiver otheruserkey node at voicecalls node firebase 
       DBREF_CALLS.child(mReceiver).child(String.valueOf(gt)).setValue(cd2); 
      } 
      endCall(); 
     } 

     @Override 
     public void onCallEstablished(Call call) { 
      Log.d(TAG, "Call established"); 
      mAudioPlayer.stopProgressTone(); 
      mCallState.setText(call.getState().toString()); 
      setVolumeControlStream(AudioManager.STREAM_VOICE_CALL); 
      mCallStart = System.currentTimeMillis(); 
      mTimestamp = GetTimeStamp.timeStamp(); 
     } 

     @Override 
     public void onCallProgressing(Call call) { 
      Log.d(TAG, "Call progressing"); 
      mAudioPlayer.playProgressTone(); 
     } 

     @Override 
     public void onShouldSendPushNotification(Call call, List<PushPair> pushPairs) { 
      // Send a push through your push provider here, e.g. GCM 
     } 
    } 
} 

我SinchCallService类是这样的:

public class SinchCallService extends Service { 

    private static final String APP_KEY = SINCH_APPLICATION_KEY; 
    private static final String APP_SECRET = SINCH_SECRET_KEY; 
    private static final String ENVIRONMENT = "sandbox.sinch.com"; 

    public static final String LOCATION = "LOCATION"; 
    public static final String CALL_ID = "CALL_ID"; 
    static final String TAG = SinchCallService.class.getSimpleName(); 

    private SinchServiceInterface mSinchServiceInterface = new SinchServiceInterface(); 
    private SinchClient mSinchClient; 
    private String mUserId; 

    private StartFailedListener mListener; 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     UserSession us = new UserSession(this); 
     System.out.println("From sinchcall oncreate" + us.getUserKey()); 
     if (!isStarted()) { 
      System.out.println("sinch not started callservice oncreate " + us.getUserKey()); 
      start(us.getUserKey()); 
     } 
    } 

    @Override 
    public void onDestroy() { 
     if (mSinchClient != null && mSinchClient.isStarted()) { 
      mSinchClient.terminate(); 
     } 
     super.onDestroy(); 
    } 


    public void start(String userName) { 
     System.out.println("sinch call service start " + userName); 
     if (mSinchClient == null) { 
      mUserId = userName; 
      mSinchClient = Sinch.getSinchClientBuilder().context(getApplicationContext()).userId(userName) 
        .applicationKey(APP_KEY) 
        .applicationSecret(APP_SECRET) 
        .environmentHost(ENVIRONMENT).build(); 

      mSinchClient.setSupportCalling(true); 
      mSinchClient.startListeningOnActiveConnection(); 

      mSinchClient.addSinchClientListener(new MySinchClientListener()); 
      mSinchClient.getCallClient().addCallClientListener(new SinchCallClientListener()); 
      mSinchClient.start(); 
      System.out.println(" sinch client started"); 
     } 
    } 

    private void stop() { 
     if (mSinchClient != null) { 
      mSinchClient.terminate(); 
      mSinchClient = null; 
     } 
    } 

    private boolean isStarted() { 
     return (mSinchClient != null && mSinchClient.isStarted()); 
    } 

    @Override 
    public IBinder onBind(Intent intent) { 
     return mSinchServiceInterface; 
    } 

    public class SinchServiceInterface extends Binder { 

     public SinchCallService getService() { 
      return SinchCallService.this; 
     } 

     public Call callPhoneNumber(String phoneNumber) { 
      return mSinchClient.getCallClient().callPhoneNumber(phoneNumber); 
     } 

     public Call callUser(String userId) { 
      return mSinchClient.getCallClient().callUser(userId); 
     } 

     public Call callUser(String userId, Map<String, String> headers) { 
      if(!isStarted()){ 
       UserSession us = new UserSession(getApplicationContext()); 
       startClient(us.getUserKey()); 
      } 
      return mSinchClient.getCallClient().callUser(userId, headers); 
     } 

     public String getUserName() { 
      return mUserId; 
     } 

     public boolean isStarted() { 
      return SinchCallService.this.isStarted(); 
     } 

     public void startClient(String userName) { 
      System.out.println("startClient called sinchcallservice" + userName); 

      if (!isStarted()) { 
       System.out.println("startClient not started callservice " + userName); 
       start(userName); 
      } 


     } 

     public void stopClient() { 
      stop(); 
     } 

     public void setStartListener(StartFailedListener listener) { 
      mListener = listener; 
     } 

     public Call getCall(String callId) { 
      return mSinchClient.getCallClient().getCall(callId); 
     } 
    } 

    public interface StartFailedListener { 
     void onStartFailed(SinchError error); 

     void onStarted(); 
    } 

    private class MySinchClientListener implements SinchClientListener { 

     @Override 
     public void onClientFailed(SinchClient client, SinchError error) { 
      if (mListener != null) { 
       mListener.onStartFailed(error); 
      } 
      mSinchClient.terminate(); 
      mSinchClient = null; 
     } 

     @Override 
     public void onClientStarted(SinchClient client) { 
      Log.d(TAG, "SinchClient started"); 
      if (mListener != null) { 
       mListener.onStarted(); 
      } 
     } 

     @Override 
     public void onClientStopped(SinchClient client) { 
      Log.d(TAG, "SinchClient stopped"); 
     } 

     @Override 
     public void onLogMessage(int level, String area, String message) { 
      switch (level) { 
       case Log.DEBUG: 
        Log.d(area, message); 
        break; 
       case Log.ERROR: 
        Log.e(area, message); 
        break; 
       case Log.INFO: 
        Log.i(area, message); 
        break; 
       case Log.VERBOSE: 
        Log.v(area, message); 
        break; 
       case Log.WARN: 
        Log.w(area, message); 
        break; 
      } 
     } 

     @Override 
     public void onRegistrationCredentialsRequired(SinchClient client, 
                 ClientRegistration clientRegistration) { 
     } 
    } 

    private class SinchCallClientListener implements CallClientListener { 

     @Override 
     public void onIncomingCall(CallClient callClient, Call call) { 
      Log.e(TAG, "Incoming call"); 
      Intent intent = new Intent(SinchCallService.this, IncomingCallScreenActivity.class); 
      intent.putExtra(CALL_ID, call.getCallId()); 
      intent.putExtra(LOCATION, call.getHeaders().get("location")); 
      intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
      SinchCallService.this.startActivity(intent); 
     } 
    } 
} 

以下是我BaseActivity.java:

public abstract class BaseActivity extends FragmentActivity implements ServiceConnection { 

    private SinchCallService.SinchServiceInterface mSinchServiceInterface; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     getApplicationContext().bindService(new Intent(this, SinchCallService.class), this, 
       BIND_AUTO_CREATE); 
    } 

    @Override 
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) { 
     if (SinchCallService.class.getName().equals(componentName.getClassName())) { 
      mSinchServiceInterface = (SinchCallService.SinchServiceInterface) iBinder; 
      onServiceConnected(); 
     } 
    } 

    @Override 
    public void onServiceDisconnected(ComponentName componentName) { 
     if (SinchCallService.class.getName().equals(componentName.getClassName())) { 
      mSinchServiceInterface = null; 
      onServiceDisconnected(); 
     } 
    } 

    protected void onServiceConnected() { 
     // for subclasses 
    } 

    protected void onServiceDisconnected() { 
     // for subclasses 
    } 

    protected SinchCallService.SinchServiceInterface getSinchServiceInterface() { 
     return mSinchServiceInterface; 
    } 

} 

我都试过,如设置

android:launchMode="singleTop" 

如果我backpress东西在CallScreenA上活动并单击通知,它将打开MainAct而不是CallScreenActivity。如何使其打开CallScreenActivity?

我试图解决与创建一个stackbuilder并将它传递给挂起的意图如下:

TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); 
stackBuilder.addParentStack(CallScreenActivity.class); 
stackBuilder.addNextIntent(notificationIntent); 
PendingIntent pendingIntent = 
     stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); 

也改变清单如下:

<activity 
    android:launchMode="singleTop" 
    android:name=".activity.calls.CallScreenActivity" 
    android:screenOrientation="portrait" 
    android:parentActivityName=".activity.main.MainAct"> 
    <meta-data 
     android:name="android.support.PARENT_ACTIVITY" 
     android:value=".activity.main.MainAct"/> 
</activity> 

但上述变化导致的应用程序崩溃与以下错误:

07-06 23:38:52.353 9182-9182/com.app E/AndroidRuntime: FATAL EXCEPTION: main 
java.lang.NullPointerException: Attempt to invoke interface method 'com.sinch.android.rtc.calling.CallClient com.sinch.android.rtc.SinchClient.getCallClient()' on a null object reference 
at com.app.services.SinchCallService$SinchServiceInterface.getCall(SinchCallService.java:150) 
at com.app.activity.calls.CallScreenActivity.endCall(CallScreenActivity.java:265) 
at com.app.activity.calls.CallScreenActivity.access$100(CallScreenActivity.java:51) 
at com.app.activity.calls.CallScreenActivity$1.onClick(CallScreenActivity.java:110) 
at android.view.View.performClick(View.java:5207) 
at android.view.View$PerformClick.run(View.java:21177) 
at android.os.Handler.handleCallback(Handler.java:739) 
at android.os.Handler.dispatchMessage(Handler.java:95) 
at android.os.Looper.loop(Looper.java:148) 
at android.app.ActivityThread.main(ActivityThread.java:5438) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:738) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:628) 

所以,如果我使用的代码没有ST ackbuilder和我按主页按钮,然后按通知我的CallSCreenACtivity打开,但如果我按下CAllSCreenACtivity内的按钮,然后按主页按钮,然后我按通知,它打开主要acitivty而不是CallSCreenACtivity。即使按了callscreenactivty上的后退按钮,我的电话仍然很有活力。

另外我已经注意到,在通知中显示的通话持续时间在按下CallScreenActivity后已停止刷新,但通话仍处于活动状态。

应用程序的流程:

对于来电: - 当应用程序启动,MainAct开始,从那里用户点击某人的个人资料,并采取ProfilesAct他按下通话键打电话给那个人,是采取到CallScreenActivity。

MainAct->ProfilesACt->CallScreenACt 

接收机: - 应用程序在后台,电话打进来时,SinchCallService使得IncomingCAllAct显示,当他接受,他被带到CallScreenActivity呼叫。

IncomingCallAct->CallSCreeenACtivity 

或可能是接收器已经在使用的应用程序,然后

any activity(could be chat activity, main acitivty etc)->IncomingCallAct->CallSCreeenACtivity 

清单应用程序的假设: -

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.app.t"> 

    <application 
     android:name=".TApplication" 
     android:allowBackup="true" 
     android:icon="@mipmap/ic_launcher" 
     android:label="@string/app_name" 
     android:supportsRtl="true" 
     android:theme="@style/Theme.AppCompat.Light.NoActionBar"> 
     <activity 
      android:name=".SplashAct" 
      android:screenOrientation="portrait"> 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 

       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 

    <activity 
      android:name=".activity.userprofile.UserProfileAct" 
      android:screenOrientation="portrait" /> 


     <activity 
      android:name=".activity.videocalls.VideoCallScreenActivity" 
      android:screenOrientation="portrait" 
      android:launchMode="singleTop"/> 

     <activity 
      android:name=".activity.videocalls.IncomingVideoCallScreenActivity" 
      android:screenOrientation="portrait" 
      android:noHistory="true"/> 


     <activity 
      android:name=".activity.main.MainAct" 
      android:launchMode="singleTop" 
      android:screenOrientation="portrait"></activity> 

      <activity android:name=".activity.chat.ChatActivity" /> 

     <service android:name=".services.MyFirebaseMessagingService"> 
      <intent-filter> 
       <action android:name="com.google.firebase.MESSAGING_EVENT" /> 
      </intent-filter> 
     </service> 

     <service android:name=".services.MyFirebaseInstanceIDService"> 
      <intent-filter> 
       <action android:name="com.google.firebase.INSTANCE_ID_EVENT" /> 
      </intent-filter> 
     </service> 

     <activity android:name=".activity.settings.SettingsmainActivity" /> 

     <service android:name=".services.SinchCallService"></service> 

     <activity 
      android:name=".activity.calls.CallScreenActivity" 
      android:launchMode="singleTop" 
      android:screenOrientation="portrait" /> 

     <activity 
      android:name=".activity.calls.IncomingCallScreenActivity" 
      android:noHistory="true" 
      android:screenOrientation="portrait" /> 

     <activity android:name=".activity.chat.NewChatActivity" /> 

     <activity android:name=".activity.chat.ChatActivity1"/> 

     <provider 
      android:name="android.support.v4.content.FileProvider" 
      android:authorities="${applicationId}.provider" 
      android:exported="false" 
      android:grantUriPermissions="true"> 
      <meta-data 
       android:name="android.support.FILE_PROVIDER_PATHS" 
       android:resource="@xml/provider_paths" /> 
     </provider> 

    </application> 

</manifest> 
+0

您可以在'CallScreenActivity'中重写'onBackPressed()'并让它开始'MainAct'。是什么原因? “MainAct”活动是否已经在运行(即:在“CallScreenActivity”下面?您需要解释您的活动之间的导航。请注意,使用“TaskStackBuilder”可能不是您想要的,因为这将永远清除任务并转储任何(这可能不是你想要的) –

+0

@DavidWasser我已经包含了应用程序的流程,你能帮我吗? – Ghanendra

+0

当用户在“CallScreenActivity”中按下BACK时会发生什么?MainAct是静止的当'CallScreenActivity'正在运行时,我还是不明白你的问题 –

回答

0

没有必要使CallScreenActivity在mainfest作为singletask或singletop,只需存储像callid这样的调用参数(它可以帮助Sinch api识别特定的调用),调用sharedpreferences或sqlite数据库中的开始时间等,将通知的意图以下:

Intent notificationIntent = new Intent(getApplicationContext(), CallScreenActivity.class); 

PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, 
     notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); 

Notification notification = new NotificationCompat.Builder(getApplicationContext()) 
     .setContentTitle("In call with " + otherusername) 
     .setSmallIcon(R.drawable.iconcall) 
     .setContentIntent(pendingIntent).build(); 
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 
notificationManager.notify(111 /* ID of notification */, notification); 

只要我们通过正确的callid,我们将能够通过点击通知恢复呼叫。