13

I have created sip application using native sip in android .In it I am getting problem in unregistering account from sip server and every time I am getting DATA_CONNECTION_LOST .I also see in android docs ,but there is no brief explanation of this error.Also it facing various erros while regiterin like in_progress ,transaction_terminated etc which are not having proper explainations in doc . Here is my code :

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.*;
import android.widget.Chronometer;
import android.net.sip.*;
import java.text.ParseException;
import commonUtilities.Prefs;

public class WalkieTalkieActivity extends Activity implements View.OnTouchListener {

    public String sipAddress = null;
    public SipManager manager = null;
    public SipProfile me = null;
    public SipAudioCall call = null;
    public SipErrorCode sipcode;
    public SipException sipexeception;
    public static WalkieTalkieActivity walkiy;

    public static WalkieTalkieActivity getInstance(Context c) {
        if (walkiy == null) {
            walkiy = new WalkieTalkieActivity();
        }
        return walkiy;
    }@
    Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        // "Push to talk" can be a serious pain when the screen keeps turning off.
        // Let's prevent that.
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        Log.e("onCreate", "onCreate");
        initializeManager(this);
    }@
    Override
    public void onStart() {
        super.onStart();
        // When we get back from the preference setting Activity, assume
        // settings have changed, and re-login with new auth info.
        initializeManager(this);
    }@
    Override
    public void onDestroy() {

        super.onDestroy();
        if (call != null) {
            call.close();
        }
        closeLocalProfile();
    }@
    Override
    protected void onResume() {
        // TODO Auto-generated method stub
        initializeManager(this);
        super.onResume();
    }
    public void initializeManager(Context ctx) {


        if (manager == null) {
            Log.e("initialising ", "ini manager");
            manager = SipManager.newInstance(ctx);
        }
        initializeLocalProfile(ctx);
    }

    public void initializeLocalProfile(final Context ctx) {
        if (manager == null) {
            updateStatus("Not Supporting.", ctx);
            Log.e("return", "manager is null ");
            return;
        }

        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
        String username = prefs.getString("namePref", Prefs.getUserName(ctx));
        String domain = prefs.getString("domainPref", "255.235.472");
        String password = prefs.getString("passPref", Prefs.getUserPassword(ctx));

        if (username.length() == 0 || domain.length() == 0 || password.length() == 0) {
            return;
        }
        try {
            SipProfile.Builder builder = new SipProfile.Builder(username, domain);
            builder.setPassword(password);
            me = builder.build();
            Intent intent = new Intent();
            intent.setAction("android.SipDemo.INCOMING_CALL");
            PendingIntent pendingIntent = PendingIntent.getBroadcast(ctx, 0, intent, Intent.FILL_IN_DATA);
            manager.open(me, pendingIntent, null);

            if (!manager.isRegistered(me.getUriString())) {
                manager.setRegistrationListener(me.getUriString(), new SipRegistrationListener() {

                    public void onRegistering(String localProfileUri) {
                        Log.e("Sip restration", "Registering with SIP Server...");
                        updateStatus("Registering with SIP Server...", ctx);
                    }

                    public void onRegistrationDone(String localProfileUri, long expiryTime) {
                        Log.e("Sip restration", "Ready");
                        updateStatus("Ready", ctx);
                    }

                    public void onRegistrationFailed(String localProfileUri, int errorCode,
                        String errorMessage) {
                        Log.e("Registration Error Code ", SipErrorCode.toString(errorCode) + errorCode);
                        updateStatus(errorCode + " " + SipErrorCode.toString(errorCode), ctx);
                    }
                });
            } else {
                Log.e("already register", "already register");
                updateStatus("Ready", ctx);
            }
        } catch (ParseException pe) {
            updateStatus("Connection Error.", ctx);
        } catch (SipException se) {
            updateStatus("Connection error.", ctx);
        }
    }

    public Boolean closeLocalProfile() {
        Log.e("Closing profile", "closing profile " + me.getUriString());

        if (manager == null) {
            return false;
        }
        try {
            if (me != null) {
                Log.e("Unregistering profile", "Un registering profile ");
                manager.unregister(me, null);
                manager.close(me.getUriString());
            }
        } catch (Exception ee) {
            Log.d("WalkieTalkieActivity/onDestroy", "Failed to close local profile.", ee);
        }
        return false;
    }
    public void initiateCall(String number, final Context ctx, final View v) {

        //      updateStatus(sipAddress);
        Log.d("Number", "" + number);
        sipAddress = number;
        Log.e("initiating call", "initiating call");
        try {
            SipAudioCall.Listener listener = new SipAudioCall.Listener() {@
                Override
                public void onCallBusy(SipAudioCall call) {
                    // TODO Auto-generated method stub
                    Log.e("buzy", "buzy");
                    super.onCallBusy(call);
                }@
                Override
                public void onCallHeld(SipAudioCall call) {
                    // TODO Auto-generated method stub
                    Log.e("held", "held");
                    super.onCallHeld(call);
                }@
                Override
                public void onCalling(SipAudioCall call) {
                    // TODO Auto-generated method stub
                    Log.e("calling", "calling");
                    super.onCalling(call);
                }@
                Override
                public void onChanged(SipAudioCall call) {
                    // TODO Auto-generated method stub
                    Log.e("changed", "changed");
                    super.onChanged(call);
                }@
                Override
                public void onError(SipAudioCall call, int errorCode,
                    String errorMessage) {
                    // TODO Auto-generated method stub
                    Log.e("call error", "error" + SipErrorCode.toString(errorCode));
                    CallingScreen.fa.finish();
                    super.onError(call, errorCode, errorMessage);

                }@
                Override
                public void onReadyToCall(SipAudioCall call) {
                    // TODO Auto-generated method stub
                    Log.e("ready to call", "ready to call ");
                    super.onReadyToCall(call);
                }@
                Override
                public void onRinging(SipAudioCall call, SipProfile caller) {
                    // TODO Auto-generated method stub
                    Log.e("ringing", "ringing");

                    super.onRinging(call, caller);
                }@
                Override
                public void onRingingBack(SipAudioCall call) {
                    // TODO Auto-generated method stub
                    Log.e("ringing back", "ringing back");
                    super.onRingingBack(call);
                }@
                Override
                public void onCallEstablished(SipAudioCall call) {
                    Log.e("call established", "call established");
                    call.startAudio();
                    updateTime(true, ctx);
                }@
                Override
                public void onCallEnded(SipAudioCall call) {
                    Log.e("call ended", "call ended");

                    updateTime(false, ctx);
                    CallingScreen.fa.finish();
                }
            };
            Log.e("param 1 ", "" + me.getUriString());
            call = manager.makeAudioCall(me.getUriString(), sipAddress + "@216.245.200.2:5060", listener, 30);
        } catch (Exception e) {
            e.printStackTrace();
            Log.i("WalkieTalkieActivity/InitiateCall", "Error when trying to close manager.", e);
            if (me != null) {
                try {
                    closeLocalProfile();
                } catch (Exception ee) {
                    ee.printStackTrace();
                    Log.i("WalkieTalkieActivity/InitiateCall",
                        "Error when trying to close manager.", ee);
                    ee.printStackTrace();
                }
            }
            if (call != null) {
                call.close();
            }
        }
    }
    public void updateStatus(final String status, final Context context) {
        // Be a good citizen.  Make sure UI changes fire on the UI thread.
        this.runOnUiThread(new Runnable() {
            public void run() {
                generateNotification(context, status);
            }
        });
    }
    public void updateTime(final Boolean status, final Context context) {
        // Be a good citizen.  Make sure UI changes fire on the UI thread.
        this.runOnUiThread(new Runnable() {
            public void run() {
                if (status) {
                    CallingScreen.fa.ch = (Chronometer) CallingScreen.fa.findViewById(R.id.time);
                    CallingScreen.fa.ch.setTypeface(CallingScreen.normal);
                    CallingScreen.fa.calling_screen_text.setVisibility(View.GONE);

                    CallingScreen.fa.ch.setVisibility(View.VISIBLE);
                    CallingScreen.fa.ch.start();
                } else {
                    CallingScreen.fa.ch.stop();
                }
            }
        });
    }

    public void updateStatus(SipAudioCall call) {
        String useName = call.getPeerProfile().getDisplayName();
        if (useName == null) {
            useName = call.getPeerProfile().getUserName();
        }
        //      updateStatus(useName + "@" + call.getPeerProfile().getSipDomain());
    }
    public boolean onTouch(View v, MotionEvent event) {
        if (call == null) {
            return false;
        } else if (event.getAction() == MotionEvent.ACTION_DOWN && call != null && call.isMuted()) {
            call.toggleMute();
        } else if (event.getAction() == MotionEvent.ACTION_UP && !call.isMuted()) {
            call.toggleMute();
        }
        return false;
    }
    public void endcall() {
        if (call != null) {
            try {
                call.endCall();
            } catch (SipException se) {
                Log.d("WalkieTalkieActivity/onOptionsItemSelected",
                    "Error ending call.", se);
            }
            call.close();
        }
    }
    public void speaker(Boolean speak) {
        if (call != null)
            call.setSpeakerMode(speak);
    }
    public static void generateNotification(Context context, String message) {
        int icon = R.drawable.ic_launcher;
        long when = System.currentTimeMillis();
        NotificationManager notificationManager = (NotificationManager)
        context.getSystemService(Context.NOTIFICATION_SERVICE);
        Notification notification = new Notification(icon, message, when);
        String title = context.getString(R.string.app_name);
        Intent notificationIntent = new Intent(context, Splash_screen.class);
        // set intent so it does not start a new activity
        notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
            Intent.FLAG_ACTIVITY_SINGLE_TOP);
        PendingIntent intent =
            PendingIntent.getActivity(context, 0, notificationIntent, 0);
        notification.setLatestEventInfo(context, title, message, intent);
        notificationManager.notify(0, notification);
    }
    public Boolean isRegistered() {
        if (manager != null && me != null)
            try {
                return manager.isRegistered(me.getUriString());
            } catch (SipException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();

            }
        return false;
    }

}

LOGCAT1

12 - 23 14: 19: 10.930: E / Unregistering profile(32139): Un registering profile
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): Failed to close local profile.
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): android.net.sip.SipException: SipService.createSession() returns null
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): at android.net.sip.SipManager.unregister(SipManager.java: 507)
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): at com.phone91.android.WalkieTalkieActivity.closeLocalProfile(WalkieTalkieActivity.java: 144)
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): at com.phone91.android.DialerActivity$1$2.onClick(DialerActivity.java: 79)
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java: 174)
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): at android.os.Handler.dispatchMessage(Handler.java: 99)
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): at android.os.Looper.loop(Looper.java: 155)
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): at android.app.ActivityThread.main(ActivityThread.java: 5520)
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): at java.lang.reflect.Method.invokeNative(Native Method)
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): at java.lang.reflect.Method.invoke(Method.java: 511)
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java: 1029)
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java: 796)
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): at dalvik.system.NativeStart.main(Native Method)

LOG CAT2 :

12-23 14:53:28.890: E/Unregistering profile(2001): Un registering profile 
12-23 14:53:30.050: E/Registration Error Code(2001): DATA_CONNECTION_LOST-10
Sneha Bansal
  • 941
  • 1
  • 13
  • 38

1 Answers1

4

I've been checking SipDemo sample code, the one I assume you used as reference for your application, an also faced this error but with registration process.

After checking Android's source code (4.1), I saw this is a bug in stack's implementation. More in detail:

  1. SIP services registers and Intend listener for updating connection information.
  2. When you try to register an SipRegistrationListener too fast (by using setRegistrationListener), as network info hasn't been updated (no intent has been received), it returns SipErrorCode.DATA_CONNECTION_LOST, but, actually, session is finally properly registered.

In you case, as you're providing SipRegistrationListener in unregister method, this process fails. An ugly work around would be wait some time for intent to be received or don't provide the listener.

You will also see that, if you replace unregister call by setRegistrationLister you will still receive same error so, something you can also try is create an upper management, this is, in onRegistrationDone callback, you can set a flag to know if you can close or not the profile. Something like:

public void updateStatus(final int status, final Context context) {
    if(status == STATUS_OK)
        registered = true;

    // Be a good citizen.  Make sure UI changes fire on the UI thread.
    this.runOnUiThread(new Runnable() {
        public void run() {
            generateNotification(context, statusToString(status));
        }
    });
}

and, when closing local profile:

public Boolean closeLocalProfile() {
    Log.e("Closing profile", "closing profile " + me.getUriString());

    if (manager == null || !registered) {
        return false;
    }
    try {
        if (me != null) {
            Log.e("Unregistering profile", "Un registering profile ");
            manager.unregister(me, null);
            manager.close(me.getUriString());
        }
    } catch (Exception ee) {
        Log.d("WalkieTalkieActivity/onDestroy", "Failed to close local profile.", ee);
    }
    return false;
}

Please note that I used an integer in updateStatus instead of a string and used a helper function, statusToString to translate status codes to strings.

As you probably noted, this would add an extra management layer that, initially, should already be in the stack but it's not. I'm not really sure this would fix all return errors (after checking source code I saw several possible errors), but should help.

jcm
  • 2,568
  • 14
  • 18
  • so that means I cant unregister account from server :( – Sneha Bansal Dec 19 '13 at 13:04
  • @Bansal_Sneha Or you can try not providing the lister as I suggested in my last update. I know is ugly but this stack seems to be really buggy :-(. – jcm Dec 19 '13 at 20:01
  • I am unregistering by passing listner null but it is not getting unregister :(what should I do – Sneha Bansal Dec 20 '13 at 11:15
  • Hello jcm ,I have updated my code and added logcat as well ..Please look through it if it helps in finding solution – Sneha Bansal Dec 23 '13 at 08:56
  • @Bansal_Sneha Sorry for the delay. Please, check my update. I hope this helps. – jcm Jan 04 '14 at 11:00
  • thank you so much but I am facing problems with registration now :( as it is giving errors like In_progress ,transaction_terminated ,client error and not getting registration .Do you have solution for this too .I am also trying to debug it – Sneha Bansal Jan 06 '14 at 05:27
  • please look through if you could help me http://stackoverflow.com/questions/21427312/ssl-exception-while-calling-with-pjsip – Sneha Bansal Jan 29 '14 at 09:56
  • @Bansal_Sneha Sorry, long time disconnected. About your registration problems, after looking into SIP stack's source code I can only suggest to do as original test application does, this is, ignore some errors and wait if final registration OK response is received. – jcm Feb 24 '14 at 21:59
  • hi,please look through it .If you can help http://stackoverflow.com/questions/24970927/regarding729-integration-in-pjsip – Sneha Bansal Jul 28 '14 at 05:54