Randomly app crash on hangup action in pjsip 2.9

501 Views Asked by At

I am trying to close the activity i used for making voip by calling finish. But i have notice that at random time instead of closing current activity. it just close entire Android App. I have attached code from manifest as well.

    <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:networkSecurityConfig="@xml/network_security_config"


            android:theme="@style/AppTheme">
            <uses-library android:name="org.apache.http.legacy" android:required="false" />

            <activity
                android:name=".FullscreenActivity"
                android:configChanges="orientation|keyboardHidden|screenSize"
                android:label="@string/app_name"
                android:launchMode="singleInstance"
                android:theme="@style/FullscreenTheme">

            </activity>

            <activity
                android:name=".MediaPresentationActivity"
                android:configChanges="orientation|keyboardHidden|screenSize"

                android:label="eFrame"
                android:launchMode="singleInstance"
                android:screenOrientation="landscape"
                android:theme="@style/Theme.AppCompat"
                >



                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.HOME" />
                    <category android:name="android.intent.category.DEFAULT" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>

            </activity>



            <activity
                android:name=".SettingsActivity"
                android:label="@string/title_activity_settings"
                android:parentActivityName=".SettingsActivity"
                android:theme="@android:style/Theme.DeviceDefault">
                <meta-data
                    android:name="android.support.PARENT_ACTIVITY"
                    android:value="org.pjsip.psua2.SettingsActivity" />
            </activity>
            <activity
                android:name=".CallActivity"
                android:configChanges="orientation|keyboardHidden|screenSize"
                android:label="@string/title_activity_call"
                android:theme="@style/Theme.AppCompat.Translucent">

            </activity>


     


        </application>

So CallActivity is the activity in which i implemented voip call. once the call is finish i have created a endbutton to close the CallActivity by calling hangupcall function from callActivity.But at some random time it does close entire app instead of CallActivity . Any help would be highly appreciated

 public void hangupCall(View view)
    {
    finish();
  }

**

error

**

2020-08-20 14:06:00.083 32264-32264/org.pjsip.pjsua2 A/libc: ../src/pjmedia/vid_port.c:700: pjmedia_vid_dev_stream *pjmedia_vid_port_get_stream(pjmedia_vid_port *): assertion "vp" failed

2020-08-20 14:06:00.686 32264-32264/org.pjsip.pjsua2 A/libc: Fatal signal 6 (SIGABRT), code -6 (SI_TKILL) in tid 32264 (rg.pjsip.pjsua2), pid 32264 (rg.pjsip.pjsua2)

entire activity code

class VideoPreviewHandler implements SurfaceHolder.Callback
{   
    public boolean videoPreviewActive = false;
        
    public void updateVideoPreview(SurfaceHolder holder) 
    {
    if (MediaPresentationActivity.currentCall != null &&
        MediaPresentationActivity.currentCall.vidWin != null &&
        MediaPresentationActivity.currentCall.vidPrev != null)
    {   
        if (videoPreviewActive) {
        VideoWindowHandle vidWH = new VideoWindowHandle();
        vidWH.getHandle().setWindow(holder.getSurface());
        VideoPreviewOpParam vidPrevParam = new VideoPreviewOpParam();
        vidPrevParam.setWindow(vidWH);      
        try {
            MediaPresentationActivity.currentCall.vidPrev.start(vidPrevParam);
        } catch (Exception e) {
            System.out.println(e);
        }
        } else {
        try {
            MediaPresentationActivity.currentCall.vidPrev.stop();
        } catch (Exception e) {
            System.out.println(e);
        }   
        }
    }
    }    
    
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
    {
    updateVideoPreview(holder);
    }



    @Override
    public void surfaceCreated(SurfaceHolder holder) 
    {
    
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) 
    {
    try {
        MediaPresentationActivity.currentCall.vidPrev.stop();
    } catch (Exception e) {
        System.out.println(e);
    }
    }    
}

public class CallActivity extends Activity
              implements Handler.Callback, SurfaceHolder.Callback
{

    public static Handler handler_;
    private static VideoPreviewHandler previewHandler = 
                                  new VideoPreviewHandler();

    private final Handler handler = new Handler(this);
    private static CallInfo lastCallInfo;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_call);

    SurfaceView surfaceInVideo = (SurfaceView)
                  findViewById(R.id.surfaceIncomingVideo);
    SurfaceView surfacePreview = (SurfaceView)
                  findViewById(R.id.surfacePreviewCapture); 
    Button buttonShowPreview = (Button) 
                  findViewById(R.id.buttonShowPreview); 
    
    if (MediaPresentationActivity.currentCall == null ||
        MediaPresentationActivity.currentCall.vidWin == null)
    {
        surfaceInVideo.setVisibility(View.GONE);        
        buttonShowPreview.setVisibility(View.GONE);
    }
    setupVideoPreview(surfacePreview, buttonShowPreview);
    surfaceInVideo.getHolder().addCallback(this);
    surfacePreview.getHolder().addCallback(previewHandler);

    handler_ = handler;
    if (MediaPresentationActivity.currentCall != null) {
        try {
        lastCallInfo = MediaPresentationActivity.currentCall.getInfo();
        updateCallState(lastCallInfo);
        } catch (Exception e) {
        System.out.println(e);
        }
    } else {
        updateCallState(lastCallInfo);
    }
    }



    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        
        WindowManager wm;
        Display display;
        int rotation;
        int orient;

        wm = (WindowManager)this.getSystemService(Context.WINDOW_SERVICE);
        display = wm.getDefaultDisplay();
        rotation = display.getRotation();
        System.out.println("Device orientation changed: " + rotation);
        
        switch (rotation) {
        case Surface.ROTATION_0:   // Portrait
            orient = pjmedia_orient.PJMEDIA_ORIENT_ROTATE_270DEG;
            break;
        case Surface.ROTATION_90:  // Landscape, home button on the right
            orient = pjmedia_orient.PJMEDIA_ORIENT_NATURAL;
            break;
        case Surface.ROTATION_180:
            orient = pjmedia_orient.PJMEDIA_ORIENT_ROTATE_90DEG;
            break;
        case Surface.ROTATION_270: // Landscape, home button on the left
            orient = pjmedia_orient.PJMEDIA_ORIENT_ROTATE_180DEG;
            break;
        default:
            orient = pjmedia_orient.PJMEDIA_ORIENT_UNKNOWN;
        }

        if (MyApp.ep != null && MediaPresentationActivity.account != null) {
            try {
            AccountConfig cfg = MediaPresentationActivity.account.cfg;
            int cap_dev = cfg.getVideoConfig().getDefaultCaptureDevice();
            MyApp.ep.vidDevManager().setCaptureOrient(cap_dev, orient,
                                  true);

            } catch (Exception e) {
            System.out.println(e);
            }
        }
    }




    @Override
    protected void onDestroy()
    {
    super.onDestroy();
    handler_ = null;
    }
    
    private void updateVideoWindow(boolean show)
    { 
    if (MediaPresentationActivity.currentCall != null &&
        MediaPresentationActivity.currentCall.vidWin != null &&
        MediaPresentationActivity.currentCall.vidPrev != null)
    {
        SurfaceView surfaceInVideo = (SurfaceView) 
                      findViewById(R.id.surfaceIncomingVideo);
        
        VideoWindowHandle vidWH = new VideoWindowHandle();      
        if (show) {
        vidWH.getHandle().setWindow(
                       surfaceInVideo.getHolder().getSurface());
        } else {
        vidWH.getHandle().setWindow(null);
        }
        try {
        MediaPresentationActivity.currentCall.vidWin.setWindow(vidWH);
        } catch (Exception e) {
        System.out.println(e);
        }       
    }
    }
     
    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
    {
    updateVideoWindow(true);
    }

    public void surfaceCreated(SurfaceHolder holder)
    {
    }

    public void surfaceDestroyed(SurfaceHolder holder)
    {
    updateVideoWindow(false);
    }

    public void acceptCall(View view)
    {
    CallOpParam prm = new CallOpParam();
    prm.setStatusCode(pjsip_status_code.PJSIP_SC_OK);
    try {
        MediaPresentationActivity.currentCall.answer(prm);
    } catch (Exception e) {
        System.out.println(e);
    }

    view.setVisibility(View.GONE);
    }


    //callend
    public void hangupCall(View view)
    {
    handler_ = null;

this.finish();


        if (MediaPresentationActivity.currentCall != null) {
        CallOpParam prm = new CallOpParam();
        prm.setStatusCode(pjsip_status_code.PJSIP_SC_DECLINE);
        try {
        MediaPresentationActivity.currentCall.hangup(prm);
        } catch (Exception e) {
        System.out.println(e);
        }
    }
    }
    
    public void setupVideoPreview(SurfaceView surfacePreview, 
                      Button buttonShowPreview)
    {
    surfacePreview.setVisibility(previewHandler.videoPreviewActive?
                         View.VISIBLE:View.GONE);
    
    buttonShowPreview.setText(previewHandler.videoPreviewActive?
                  getString(R.string.hide_preview):
                  getString(R.string.show_preview));        
    }
    
    public void showPreview(View view)
    {
    SurfaceView surfacePreview = (SurfaceView)
                      findViewById(R.id.surfacePreviewCapture);

    Button buttonShowPreview = (Button) 
                  findViewById(R.id.buttonShowPreview);
    
    
    previewHandler.videoPreviewActive = !previewHandler.videoPreviewActive;
    
    setupVideoPreview(surfacePreview, buttonShowPreview);

    previewHandler.updateVideoPreview(surfacePreview.getHolder());
    }

    private void setupVideoSurface()
    {


    SurfaceView surfaceInVideo = (SurfaceView)
                  findViewById(R.id.surfaceIncomingVideo);
    SurfaceView surfacePreview = (SurfaceView)
                  findViewById(R.id.surfacePreviewCapture);
    Button buttonShowPreview = (Button)
                  findViewById(R.id.buttonShowPreview);
    surfaceInVideo.setVisibility(View.VISIBLE);
    buttonShowPreview.setVisibility(View.VISIBLE);
    surfacePreview.setVisibility(View.GONE);
    }

    @Override
    public boolean handleMessage(Message m)
    {
    if (m.what == MediaPresentationActivity.MSG_TYPE.CALL_STATE) {

        lastCallInfo = (CallInfo) m.obj;
        updateCallState(lastCallInfo);

    } else if (m.what == MediaPresentationActivity.MSG_TYPE.CALL_MEDIA_STATE) {

        if (MediaPresentationActivity.currentCall.vidWin != null) {
        /* Set capture orientation according to current
         * device orientation.
         */
        onConfigurationChanged(getResources().getConfiguration());
        /* If there's incoming video, display it. */
        setupVideoSurface();
        //showPreview(null);
        }

    } else {

        /* Message not handled */
        return false;

    }

    return true;
    }

    private void updateCallState(CallInfo ci) {
    TextView tvPeer  = (TextView) findViewById(R.id.textViewPeer);
    TextView tvState = (TextView) findViewById(R.id.textViewCallState);
    Button buttonHangup = (Button) findViewById(R.id.buttonHangup);
    Button buttonAccept = (Button) findViewById(R.id.buttonAccept);
    String call_state = "";

        if (ci == null) {
        buttonAccept.setVisibility(View.GONE);

        tvState.setText("Call disconnected");
        return;
    }
        buttonHangup.setText("OK");
    if (ci.getRole() == pjsip_role_e.PJSIP_ROLE_UAC) {
        buttonAccept.setVisibility(View.GONE);
    }

    if (ci.getState() <
        pjsip_inv_state.PJSIP_INV_STATE_CONFIRMED)
    {
        if (ci.getRole() == pjsip_role_e.PJSIP_ROLE_UAS) {
            call_state = "Incoming call..";

        //  showPreview(null);
            /* Default button texts are already 'Accept' & 'Reject' */
        } else {
        buttonHangup.setText("Cancel");
        call_state = ci.getStateText();
        }
    }
    else if (ci.getState() >=
         pjsip_inv_state.PJSIP_INV_STATE_CONFIRMED)
    {
        buttonAccept.setVisibility(View.GONE);
        call_state = ci.getStateText();
        if (ci.getState() == pjsip_inv_state.PJSIP_INV_STATE_CONFIRMED) {
        buttonHangup.setText("Hangup");
        } else if (ci.getState() ==
               pjsip_inv_state.PJSIP_INV_STATE_DISCONNECTED)
        {
        buttonHangup.setText("OK");
        call_state = "Call disconnected: " + ci.getLastReason();
        }
    }

    tvPeer.setText(ci.getRemoteUri());
    tvState.setText(call_state);
    }
}
2

There are 2 best solutions below

1
tomtom On BEST ANSWER

I also had the same issue. I couldn't find what had cause that issue. call end function and finish are both done one after other in hangup function. what i did was create a delay in finish function after call end function and it did worked without any further crash issue. But we will see a delay in ending current Activity. At least better than a crash

0
David Wasser On

It looks like you are using some library that has native code running. Probably the native code is still running even after you've finished your Activity and it is trying to access something that has been reclaimed by the garbage collector. This implies that you need to close or shutdown whatever is going on in the native code before you finish your Activity.

Check the documentation for whatever native libraries you are using about how to release resources or shutdown background or pending operations.