pjsip 2.9 中的挂断操作随机应用程序崩溃

Randomly app crash on hangup action in pjsip 2.9

我正在尝试通过调用 finish 来关闭我用来制作 voip 的 activity。但我注意到在随机时间而不是关闭电流 activity。它只是关闭整个 Android 应用程序。我也附上了清单中的代码。

    <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>

所以 CallActivity 是我实现 voip 呼叫的 activity。通话结束后,我创建了一个结束按钮来关闭 CallActivity,方法是在某个随机时间从 callActivity.But 调用 hangupcall 函数,它会关闭整个应用程序而不是 CallActivity 。任何帮助将不胜感激

 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)

整个activity代码

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);
    }
}

看起来您正在使用一些具有本机代码的库 运行。可能本机代码仍然是 运行,甚至在您完成 Activity 之后,它正在尝试访问已被垃圾收集器回收的内容。这意味着您需要在完成 Activity.

之前关闭或关闭本机代码中发生的任何事情

查看您正在使用的任何本机库的文档,了解如何释放资源或关闭后台或挂起的操作。

我也遇到了同样的问题。我找不到导致该问题的原因。 call end function 和finish 都是在hangup function 中依次完成的。我所做的是在调用结束函数后在完成函数中创建一个延迟,并且它确实在没有任何进一步的崩溃问题的情况下工作。但是我们会看到结束当前 Activity 的延迟。至少比崩溃好