How to perform call in Pjsip Android with local server?
I used
User-Agent: Pjsua2 Android 2.6-svn
I made successful registraion after which i tried to call but it throws forbidden(503)
My Registraion Code :
AccountConfig accCfg = new AccountConfig();
accCfg.setIdUri("sip:localhost");
accCfg.getNatConfig().setIceEnabled(true);
accCfg.getVideoConfig().setAutoTransmitOutgoing(true);
accCfg.getVideoConfig().setAutoShowIncoming(true);
//Like 123.12.12.23
accCfg.getRegConfig().setRegistrarUri("sip:172.16.4.124");
AuthCredInfoVector creds = accCfg.getAuthCreds();
creds.clear();
if (username.length() != 0) {
creds.add(new AuthCredInfo("Digest", "*", "abc#172.16.4.124", 0,
"123"));
}
StringVector proxies = accCfg.getSipConfig().getProxies();
proxies.clear();
if (proxy.length() != 0) {
proxies.add("sip:172.16.4.124");
}
accCfg.getSipConfig().setProxies(proxies);
/* Enable ICE */
accCfg.getNatConfig().setIceEnabled(true);
try {
account.add(accCfg);
} catch (Exception e) {
e.printStackTrace();
Log.i(TAG, "Exception in Dialog");
}
}
For Making call I used
public void makeCall(View view) {
if (buddyListSelectedIdx == -1)
return;
/* Only one call at anytime */
if (currentCall != null) {
return;
}
HashMap<String, String> item = (HashMap<String, String>) buddyListView.
getItemAtPosition(buddyListSelectedIdx);
String buddy_uri = item.get("uri");
MyCall call = new MyCall(account, -1);
SendInstantMessageParam param = new SendInstantMessageParam();
param.setContent("Hello Pjsip");
param.setContentType("text");
CallOpParam prm = new CallOpParam(true);
try {
call.makeCall(buddy_uri, prm);
// call.delete();
// call.sendInstantMessage(param);
} catch (Exception e) {
e.printStackTrace();
call.delete();
return;
}
currentCall = call;
showCallActivity();
}
I am able to connect call with sip default client like sip:localhost and other sip provider like linphone but getting forbidden with our server.
Experts please help.
Thanks alot to myself, finally i get the solution after 3 day workout,
had missing portnumber for my amazon server, makes me to get connected and made a sippy call between sip ends.
Related
I'm building a PJSUA2 (PJSIP 2.8) Android app and I have some issues: i.e. only on incoming call, call state remains in "PJSIP_INV_STATE_CONNECTING" and after 32 seconds the call drops.
I'm looking for the cause of the issue since several days, I googled a lot and all what I found is: in most situations this issue is related to NAT management or network issues related to NAT. In a few words: in most cases the called party does not receive the ACK after answering the call.
Finally I was able to log all SIP messages between my app and the SIP server and found that my app receives the ACK from the server, so I suppose it's not a network related issue.
I compiled PJSIP 2.8 with OpenSSL and SRTP support, but without video support (I don't need it at least at the moment). If it makes any difference, the app has a target version 28 and minimum SDK version 19.
I tried several apps on the market and they work fine enough with and without SRTP and with all signaling transports (UDP, TCP, TLS), WebRTC works fine too (tested with SipML5), so I would exclude a server misconfiguration. My app does the same (except SRTP with which I have some issues at the moment).
I tried with a SIP provider too (MessageNet) using UDP and the behaviour is always the same. I tried to use compact SIP messages and it behaves the same, with and without uri parameters, with and without STUN and or ICE and nothing changes. Mobile network and WiFi networks give the same results.
I tried to debug inside PJSIP library too, but without any success, then I tried to follow the code, to understand what I was doing wrong, but it doesn't seem to me there is something evidently wrong.
The following is the code (last version) which initializes PJSIP:
public class SipService extends Service {
private Looper serviceLooper;
private ServiceHandler serviceHandler;
private final Messenger mMessenger = new Messenger(new IncomingHandler());
private LocalBroadcastManager localBroadcast;
private LifecycleBroadcastReceiver lifecycleBroadcastReceiver;
private boolean lastCheckConnected;
private Endpoint endpoint;
private LogWriter logWriter;
private EpConfig epConfig;
private final List<ManagedSipAccount> accounts = new ArrayList<>();
private final Map<String, Messenger> eventRegistrations = new HashMap<>();
#TargetApi(Build.VERSION_CODES.N)
#Override
public void onCreate() {
super.onCreate();
String userAgent = "MyApp";
try {
PackageInfo pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
String appLabel = (pInfo.applicationInfo.labelRes == 0 ? pInfo.applicationInfo.nonLocalizedLabel.toString() : getString(pInfo.applicationInfo.labelRes));
userAgent = appLabel + "/" + pInfo.versionName;
} catch (PackageManager.NameNotFoundException e) {
Log.e("SipService", "Unable to get app version", e);
}
try {
endpoint = new MyAppEndpoint();
endpoint.libCreate();
epConfig = new EpConfig();
// Logging
logWriter = new PJSIPToAndroidLogWriter();
epConfig.getLogConfig().setWriter(logWriter);
epConfig.getLogConfig().setLevel(5);
// UA
epConfig.getUaConfig().setMaxCalls(4);
epConfig.getUaConfig().setUserAgent(userAgent);
// STUN
StringVector stunServer = new StringVector();
stunServer.add("stun.pjsip.org");
epConfig.getUaConfig().setStunServer(stunServer);
// General Media
epConfig.getMedConfig().setSndClockRate(16000);
endpoint.libInit(epConfig);
// UDP transport
TransportConfig udpCfg = new TransportConfig();
udpCfg.setQosType(pj_qos_type.PJ_QOS_TYPE_VOICE);
endpoint.transportCreate(pjsip_transport_type_e.PJSIP_TRANSPORT_UDP, udpCfg);
// TCP transport
TransportConfig tcpCfg = new TransportConfig();
//tcpCfg.setPort(5060);
endpoint.transportCreate(pjsip_transport_type_e.PJSIP_TRANSPORT_TCP, tcpCfg);
// TLS transport
TransportConfig tlsCfg = new TransportConfig();
endpoint.transportCreate(pjsip_transport_type_e.PJSIP_TRANSPORT_TLS, tlsCfg);
endpoint.libStart();
} catch (Exception e) {
throw new RuntimeException("Unable to initialize and start PJSIP", e);
}
ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
lastCheckConnected = activeNetwork != null && activeNetwork.isConnected();
updateForegroundNotification();
startForeground(MyAppConstants.N_FOREGROUND_NOTIFICATION_ID, buildForegroundNotification());
localBroadcast = LocalBroadcastManager.getInstance(this);
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
serviceLooper = thread.getLooper();
serviceHandler = new ServiceHandler(serviceLooper);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
// Register LifeCycleBroadcastReceiver to receive network change notification
// It seems it's mandatory to do it programmatically since Android N (24)
lifecycleBroadcastReceiver = new LifecycleBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE");
registerReceiver(lifecycleBroadcastReceiver, intentFilter);
}
// Initialization
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
if (prefs != null) {
try {
CodecInfoVector codecs = endpoint.codecEnum();
SharedPreferences.Editor editor = prefs.edit();
for (int i = 0; i < codecs.size(); i++) {
CodecInfo codec = codecs.get(i);
int priority = prefs.getInt("codecs.audio{" + codec.getCodecId() + "}", 0);
try {
endpoint.codecSetPriority(codec.getCodecId(), (short) priority);
codec.setPriority((short) priority);
} catch (Exception e) {
Log.e("SipService", "Unexpected error setting codec priority for codec " + codec.getCodecId(), e);
}
}
} catch (Exception e) {
Log.e("SipService", "Unexpected error loading codecs priorities", e);
}
}
}
#Override
public void onDestroy() {
for (Account acc : accounts) {
acc.delete();
}
accounts.clear();
try {
endpoint.libDestroy();
} catch (Exception e) {
e.printStackTrace();
}
endpoint.delete();
endpoint = null;
epConfig = null;
if (lifecycleBroadcastReceiver != null) {
unregisterReceiver(lifecycleBroadcastReceiver);
}
super.onDestroy();
}
.......
}
And the following is my Account class with creation and registration code:
public class ManagedSipAccount extends Account {
public final String TAG;
private final VoipAccount account;
private final PhoneAccountHandle handle;
private final SipService service;
private final AccountStatus status;
private final Map<Integer, VoipCall> calls = new HashMap<>();
private final Map<String, VoipBuddy> buddies = new HashMap<>();
private AccountConfig acfg;
private List<SrtpCrypto> srtpCryptos = new ArrayList<>();
private AuthCredInfo authCredInfo;
public ManagedSipAccount(SipService service, VoipAccount account, PhoneAccountHandle handle) {
super();
TAG = "ManagedSipAccount/" + account.getId();
this.service = service;
this.account = account;
this.handle = handle;
this.status = new AccountStatus(account.getUserName() + "#" + account.getHost());
acfg = new AccountConfig();
}
public void register(Map<String, String> contactParameters) throws Exception {
StringBuilder contactBuilder = new StringBuilder();
for (Map.Entry<String, String> entry : contactParameters.entrySet()) {
contactBuilder.append(';');
contactBuilder.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
contactBuilder.append("=\"");
contactBuilder.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
contactBuilder.append("\"");
}
StringBuilder logBuilder = new StringBuilder();
logBuilder.append("Registering: ");
logBuilder.append(account.getProtocol().name());
/*logBuilder.append('(');
logBuilder.append(service.getTransport(account.getProtocol()));
logBuilder.append(')');*/
if (account.isEncryptionSRTP()) {
logBuilder.append(" SRTP");
}
if (account.isIce()) {
logBuilder.append(" ICE");
}
Log.d(TAG, logBuilder.toString());
String idUri = "sip:" + account.getUserName();
if (!"*".equals(account.getRealm())) {
idUri += "#" + account.getRealm();
}
else {
idUri += "#127.0.0.1" /*+ account.getHost()*/;
}
acfg.setIdUri(idUri);
acfg.getRegConfig().setRegistrarUri("sip:" + account.getHost() + ":" + account.getPort() + ";transport=" + account.getProtocol().name().toLowerCase());
acfg.getRegConfig().setRetryIntervalSec(account.getRetryInterval());
acfg.getRegConfig().setRegisterOnAdd(false);
acfg.getSipConfig().setContactUriParams(contactBuilder.toString());
// NAT management
acfg.getNatConfig().setSipStunUse(pjsua_stun_use.PJSUA_STUN_USE_DEFAULT);
if (account.isIce()) {
acfg.getNatConfig().setIceEnabled(true);
acfg.getNatConfig().setIceAlwaysUpdate(true);
acfg.getNatConfig().setIceAggressiveNomination(true);
}
else {
acfg.getNatConfig().setSdpNatRewriteUse(1);
}
acfg.getMediaConfig().getTransportConfig().setQosType(pj_qos_type.PJ_QOS_TYPE_VOICE);
if (account.isEncryptionSRTP()) {
acfg.getMediaConfig().setSrtpUse(pjmedia_srtp_use.PJMEDIA_SRTP_MANDATORY);
acfg.getMediaConfig().setSrtpSecureSignaling(0);
//acfg.getMediaConfig().getSrtpOpt().setKeyings(new IntVector(2));
acfg.getMediaConfig().getSrtpOpt().getKeyings().clear();
acfg.getMediaConfig().getSrtpOpt().getKeyings().add(pjmedia_srtp_keying_method.PJMEDIA_SRTP_KEYING_SDES.swigValue());
acfg.getMediaConfig().getSrtpOpt().getKeyings().add(pjmedia_srtp_keying_method.PJMEDIA_SRTP_KEYING_DTLS_SRTP.swigValue());
acfg.getMediaConfig().getSrtpOpt().getCryptos().clear();
StringVector cryptos = Endpoint.instance().srtpCryptoEnum();
for (int i = 0; i < cryptos.size(); i++) {
SrtpCrypto crypto = new SrtpCrypto();
crypto.setName(cryptos.get(i));
crypto.setFlags(0);
srtpCryptos.add(crypto);
acfg.getMediaConfig().getSrtpOpt().getCryptos().add(crypto);
}
}
else {
acfg.getMediaConfig().setSrtpUse(pjmedia_srtp_use.PJMEDIA_SRTP_DISABLED);
acfg.getMediaConfig().setSrtpSecureSignaling(0);
}
authCredInfo = new AuthCredInfo("digest",
account.getRealm(),
account.getAuthenticationId() != null && account.getAuthenticationId().trim().length() > 0 ? account.getAuthenticationId() : account.getUserName(),
0,
account.getPassword());
acfg.getSipConfig().getAuthCreds().add( authCredInfo );
acfg.getIpChangeConfig().setHangupCalls(false);
acfg.getIpChangeConfig().setShutdownTp(true);
create(acfg);
ConnectivityManager cm = (ConnectivityManager)service.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null && activeNetwork.isConnected();
if (isConnected) {
setRegistration(true);
}
}
#Override
public void onRegStarted(OnRegStartedParam prm) {
super.onRegStarted(prm);
Log.d(TAG, "Status: Registering...");
status.setStatus(AccountStatus.Status.REGISTERING);
service.updateStatus(this);
}
#Override
public void onRegState(OnRegStateParam prm) {
super.onRegState(prm);
try {
Log.d(TAG, "Registration state: " + prm.getCode().swigValue() + " " + prm.getReason());
AccountInfo ai = getInfo();
status.setStatus(ai.getRegIsActive() ? AccountStatus.Status.REGISTERED : AccountStatus.Status.UNREGISTERED);
Log.d(TAG, "Status: " + status.getStatus().name() + " " + super.getInfo().getUri());
service.updateStatus(this);
} catch (Exception e) {
e.printStackTrace();
}
}
.....
}
Finally, how I answer the code at the moment in a class which extends the PJSIP's Call class:
#Override
public void answerCall() {
Log.d(TAG, "Answering call...");
CallOpParam prm = new CallOpParam(true);
prm.setStatusCode(pjsip_status_code.PJSIP_SC_OK);
prm.getOpt().setAudioCount(1);
prm.getOpt().setVideoCount(0);
try {
this.answer(prm);
} catch (Exception e) {
e.printStackTrace();
}
}
I also tried with new CallOpParam(); with just the status code and nothing else, but nothing changes.
One note: I created the IdUri as sip:username#127.0.0.1 because without the host the resulting contact was and I thought that the missing user part may be the cause of the issue or part of it.
The following is the trace of the app <-> my Asterisk server communication during call (linked because of content length exceed).
https://gist.github.com/ivano85/a212ddc9a808f3cd991234725c2bdb45
The ServerIp is an internet public IP, while the MyIp[5.XXX.XXX.XXX] is my phone's public IP.
As you can see from the log, my app sends a 100 Trying, then a 180 Ringing when the phone rings, then the user answers and the app sends a 200 OK. The server replies with a ACK message (I would say it's not a NAT issue, because PJSIP receives the ACK). I see the same from Asterisk.
After this I would expect the call goes from PJSIP_INV_STATE_CONNECTING to PJSIP_INV_STATE_CONFIRMED, but it does not happen, so PJSIP continues to send a 200 OK and receive the ACK every about 2 seconds, until the call times out after 32 seconds and PJSIP disconnects the call (sending a BYE).
I'm starting to think that PJSIP just ignores ACK messages and just has a wrong behaviour. Please help me to understand what is happening here. I would appreciate it so much!
Obviously let me know if you think that more details are needed.
I have a problem pushing data to my index. My code is as follows:
Client client = new Client("APP_ID", "SEARCH_ID");
Index myIndex = client.initIndex("test");
JSONObject jsonObject = null;
try {
jsonObject = new JSONObject()
.put("name", "Jimmie")
.put("username", "Barninger")
} catch (JSONException e) {
e.printStackTrace();
}
myIndex.addObjectAsync(jsonObject, null);
However nothing happens, and no data is visible in my dashboard. What am I doing wrong?
I had to change the api keys which previously was SEARCH_ID. I changed it to my ADMIN_API_KEY:
Client client = new Client("APP_ID", "ADMIN_API_KEY");
This is because the search-only API key can only be used for searching, while the Admin API key can change, delete or add an object.
The full code is now:
Client client = new Client("APP_ID", "ADMIN_API_KEY");
Index myIndex = client.initIndex("test");
JSONObject object = null;
try {
object = new JSONObject()
.put("username", "Jimmie")
.put("name", "Barninger");
} catch (JSONException e) {
e.printStackTrace();
}
// myIndex.addObjectAsync(object, "myID", null);
myIndex.addObjectAsync(object, "id", null);
In order to understand more, please replace the addobjectAsync line with something like this:
index.addObjectAsync(object, new CompletionHandler() {
#Override
public void requestCompleted(JSONObject content, AlgoliaException error) {
if (error != null) {
// Check what is the error Here
}
}
}
Hey i am developing Chat Application using XMPP Smack Library. Recently i am working on Group Chat While sending Group message some message will be drop so receiver wouldn't receives message from the sender side. it will gives me 400 bad request.
it is working sometimes. and sometimes not work
here i found this kind of message in 400 bad request.
<?xml version="1.0" encoding="UTF-8"?>
<message to="156#abc.com/Android" id="nXlV6-1144" type="error" from="24#confrence.abc.com/156#abc.com.com">
<received xmlns="urn:xmpp:receipts" id="nXlV6-1142" />
<error code="400" type="modify">
<bad-request xmlns="urn:ietf:params:xml:ns:xmpp-stanzas" />
</error>
</message>
if successfully send message it will give this kind of message.
<?xml version="1.0" encoding="UTF-8"?>
<message to="156#abc.com/Android" id="nXlV6-1411" type="groupchat" from="24#conference.abc.com/156#abc.com">
<body>eyu4u4</body>
<chatDetail xmlns="jabber:x:oob">
<UID>156</UID>
<time>04:20 PM</time>
<user_icon>24_group_icon.jpg</user_icon>
<SentTime>1474368652960</SentTime>
<USERName>vasudev89</USERName>
<user_name>cryan</user_name>
<message>eyu4u4</message>
<type>group</type>
<phone_number>24</phone_number>
</chatDetail>
<request xmlns="urn:xmpp:receipts" />
</message>
how i can send message persistently? Any idea?
Thank You in Advance.
here is my code sending muc message:
public boolean sendGroupMessage(Message message, String strGroupID) {
DeliveryReceiptRequest.addTo(message);
try {
Log.i(TAG, "sendGroupMessage");
//Log.i("JOIN MUC","To join group chat: " + groupChat.getClassId());
// Get the MultiUserChatManager
MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(AbstractXMPPConnection);
// Create a MultiUserChat using an XMPPConnection for a room
MultiUserChat muc = manager.getMultiUserChat(strGroupID + AppWSConstants.XMPP_JID_GROUP_CHAT_SUFFIX);
muc.sendMessage(message);
return true;
} catch (NotConnectedException e) {
e.printStackTrace();
}
return false;
}
#LearnPainLess, follow these steps to solve group chat issue
-when creating groups, save the jid of group in the database, like "somegroup#conference.{domain}.com"
-create background task for creating xmpp connection (this way it will always be connected)
-after logging in to xmpp, get the group names from the database and connect to them
also, in openfire, Group Chat > Group Chat Settings > Edit Icon > Default Room Settings > Check "Make Room Persistant"
also, in other settings > Never kick idle users
I have an XmppBase class where i put all my xmpp code
All listeners in seperate folder
Connection is stored in static variable and i retrive it using
Utils.getConnection()
// this function m calling from background service and everywhere if not connectect to xmpp
public static XMPPConnection CreateXmppConnection() {
if (Utils.getConnection() == null) {
try {
Boolean isConnected = new XmppAsync(mUsername, mPassword,context).execute().get();
if (isConnected && Utils.getConnection() != null) {
RegisterConnListeners(Utils.getConnection());
updateMyProfileImg();
// connect to all groups
DBAdapter adapter = new DBAdapter(context);
adapter.openForRead();
List<UserDetail> groups = new ArrayList<>();
adapter.addAllGroups(groups);
adapter.addPastChatGroups(groups);
adapter.close();
for(UserDetail g : groups)
{
CreateXmppMUCSession(g.getGroupTemp());
}
return Utils.getConnection();
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return null;
} else
return Utils.getConnection();
}
// get muc chat manager
public static MultiUserChatManager getMucManager() {
if(mucManager != null)
return mucManager;
if (Utils.getConnection() != null) {
return MultiUserChatManager.getInstanceFor(Utils.getConnection());
} else {
if (CreateXmppConnection() != null)
return MultiUserChatManager.getInstanceFor(Utils.getConnection());
else {
Log.v("error", "Some Error Occured");
Toast.makeText(context, "Cant Connect to Xmpp", Toast.LENGTH_SHORT).show();
return null;
}
}
}
// create muc session and m passing group name - call when you open chat page
public static void CreateXmppMUCSession(String gName)
{
RegisterGroupChatListeners(gName);
}
// connect to muc if not already connected
public static void RegisterGroupChatListeners(String groupName)
{
try {
mStateManager = getChatStateManager();
multiUserChat = getMUC(groupName);
// if(multiUserChat != null) {
multiUserChat.addMessageListener(new MyMUCMessageListener());
try {
if (!multiUserChat.isJoined()) {
DiscussionHistory discussionHistory = new DiscussionHistory();
discussionHistory.setMaxStanzas(0);
multiUserChat.join(new MyPrefrence(context).getUsername().split("#")[0], "123",
discussionHistory, SmackConfiguration.getDefaultPacketReplyTimeout());
}
} catch (SmackException.NoResponseException e) {
e.printStackTrace();
} catch (XMPPException.XMPPErrorException e) {
e.printStackTrace();
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
}
// }
}
catch (Exception ex)
{
//
}
}
// get muc
public static MultiUserChat getMUC(String groupName)
{
// Log.v("nick",multiUserChat.getNickname() + " , g = " + groupName);
// if(multiUserChat != null && multiUserChat.getRoom().contains(groupName))
// {
// return multiUserChat;
// }
if (Utils.getConnection() != null) {
MultiUserChatManager chatManager = getMucManager();
if (chatManager != null) {
return chatManager.getMultiUserChat(groupName);
} else {
Toast.makeText(context, "Cannot create Chat", Toast.LENGTH_SHORT).show();
return null;
}
} else {
if (CreateXmppConnection() != null) {
MultiUserChatManager chatManager = getMucManager();
if (chatManager != null) {
return chatManager.getMultiUserChat(groupName);
} else {
Toast.makeText(context, "Cannot create Chat", Toast.LENGTH_SHORT).show();
return null;
}
}
else {
Toast.makeText(context, "Cannot create Chat", Toast.LENGTH_SHORT).show();
return null;
}
}
}
and whenever i want to send message i just call this
public static Boolean sendMUCChatMsg(Message msg)
{
if(multiUserChat != null)
try {
multiUserChat.sendMessage(msg);
return true;
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
}
return false;
}
Sorry if it looks clumpsy, if I missed any function there let me know, but this is working code which i am using
try this,
I modified your last function
static MultiUserChat multiUserChat;
// call this function when you open the chat window
private void CreateGroupConnection(String strGroupID ) {
// Get the MultiUserChatManager
MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(AbstractXMPPConnection);
// Create a MultiUserChat using an XMPPConnection for a room
MultiUserChat multiUserChat = manager.getMultiUserChat(strGroupID + AppWSConstants.XMPP_JID_GROUP_CHAT_SUFFIX);
return multiUserChat;
}
// whenever sending message from chat call this
publilc static void sendMucMessage(Message message){
if(multiUserChat != null)
multiUserChat.sendMessage(message);
}
I am working on "seen and delivered" in MUC and facing with this issue when replying back with the same packet id, still testing but I think in your case you should move your xmpp connection to background service and after connecting to xmpp on device launch up, connect to all the muc in your database. This way you will always be connected to groups.
cause : according to me, when the other user is not connected to the muc and you send a message or when you reply to the group with the same packet id.
Note: I am using multiuserchat.sendmessage to send group message and chat.sendmessage to send message to single user
SMACK 4.1
** update **
I fixed it by creating new packet instead of modifying the one i am receiving
here is the packet
Message msgg = new Message();
msgg.setBody(message.getPacketID());
msgg.setSubject(MessageModel.CHAT_STATUS_SEEN + "");
XmppBase.sendMUCChatMsg(msgg);
in your case, try with simple packet first. if all works well, then add extension one by one and see where you get the error, Thanks
i have a openfire server running on my localhost and i am successfully able to send and receive messages to registered users. however i am not been able to get all users from server. i am logged in with user that doesn't have a administration access. so do i need to give any permission on server side?
The code i am using for getting all users is..
if ( xmpp.getConnection()== null || !xmpp.getConnection().isConnected())
return;
try {
UserSearchManager usm = new UserSearchManager(xmpp.getConnection());
Form searchForm = usm.getSearchForm("search." + xmpp.getConnection().getServiceName());
Form answerForm = searchForm.createAnswerForm();
UserSearch userSearch = new UserSearch();
answerForm.setAnswer("Username", true);
answerForm.setAnswer("search", userName);
ReportedData data = userSearch.sendSearchForm(xmpp.getConnection(), answerForm, "search." + xmpp.getConnection().getServiceName());
for (ReportedData.Row row : data.getRows())
{
arrayList.add(row.getValues("Username").toString());
}
} catch (Exception e) {
e.printStackTrace();
}
i tried some solutions that shows to use Roster class, however that is also not helping me. Can anyone show what i am doing wrong or if i need to give any permission as i am not logged in as admin?
The error i am getting is..
org.jivesoftware.smack.XMPPException$XMPPErrorException: XMPPError: remote-server-not-found
Thanks :)
This is how I am getting all users from openfire
You actually have to pass wildcard(*) for the username
Here's the working code
Utils.getConnection() - my xmpp connection
public static void getAllXmppUsers()
{
try {
UserSearchManager manager = new UserSearchManager(Utils.getConnection());
String searchFormString = "search." + Utils.getConnection().getServiceName();
Log.d("***", "SearchForm: " + searchFormString);
Form searchForm = null;
searchForm = manager.getSearchForm(searchFormString);
Form answerForm = searchForm.createAnswerForm();
UserSearch userSearch = new UserSearch();
answerForm.setAnswer("Username", true);
answerForm.setAnswer("search", "*");
ReportedData results = userSearch.sendSearchForm(Utils.getConnection(), answerForm, searchFormString);
if (results != null) {
List<ReportedData.Row> rows = results.getRows();
for (ReportedData.Row row : rows) {
Log.d("***", "row: " + row.getValues("Username").toString());
}
} else {
Log.d("***", "No result found");
}
} catch (SmackException.NoResponseException e) {
e.printStackTrace();
} catch (XMPPException.XMPPErrorException e) {
e.printStackTrace();
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
}
}
Try this code. I tweak this code from this answer
UserSearchManager usm= new UserSearchManager(xmpp.getConnection());
Form searchForm = usm.getSearchForm("search." +xmpp.getConnection().getServiceName());
Form answerForm = searchForm.createAnswerForm();
answerForm.setAnswer("Username", true);
answerForm.setAnswer("search", userName);
ReportedData data = usm
.getSearchResults(answerForm, "search." + xmpp.getConnection().getServiceName());
if (data.getRows() != null) {
for (ReportedData.Row row: data.getRows()) {
for (String jid:row.getValues("jid")) {
System.out.println(jid);
}
}
}
Smack is used to create a client. A client is used by one user. A user typically does not have access to all users of the server. Users do have contact lists, or rosters though, where you an add other users.
I have tried jainsip example in Mobicents restcomm-android-sdk.Its worked for me but i am not able create bye message from client side properly.
I created a Bye Message class like this
public class Bye {
public Request MakeRequest(SipManager sipManager) throws ParseException,
InvalidArgumentException {
AddressFactory addressFactory = sipManager.addressFactory;
SipProvider sipProvider = sipManager.sipProvider;
MessageFactory messageFactory = sipManager.messageFactory;
HeaderFactory headerFactory = sipManager.headerFactory;
// Create addresses and via header for the request
Address fromAddress = addressFactory.createAddress("sip:"
+ sipManager.getSipProfile().getSipUserName() + "#"
+ sipManager.getSipProfile().getRemoteIp());
fromAddress.setDisplayName(sipManager.getSipProfile().getSipUserName());
Address toAddress = addressFactory.createAddress("sip:"
+ sipManager.getSipProfile().getSipUserName() + "#"
+ sipManager.getSipProfile().getRemoteIp());
toAddress.setDisplayName(sipManager.getSipProfile().getSipUserName());
Address contactAddress = sipManager.createContactAddress();
ArrayList<ViaHeader> viaHeaders = sipManager.createViaHeader();
URI requestURI = addressFactory.createAddress(
"sip:" + sipManager.getSipProfile().getRemoteEndpoint())
.getURI();
// Build the request
CallIdHeader callIdHeader = sipManager.sipProvider.;
final Request request = messageFactory.createRequest(requestURI,
Request.BYE, sipProvider.getNewCallId(),
headerFactory.createCSeqHeader(1l, Request.BYE),
headerFactory.createFromHeader(fromAddress, "c3ff411e"),
headerFactory.createToHeader(toAddress, null), viaHeaders,
headerFactory.createMaxForwardsHeader(70));
// Add the contact header
request.addHeader(headerFactory.createContactHeader(contactAddress));
ExpiresHeader eh = headerFactory.createExpiresHeader(300);
request.addHeader(eh);
// Print the request
System.out.println(request.toString());
return request;
// Send the request --- triggers an IOException
// sipProvider.sendRequest(request);
// ClientTransaction transaction = sipProvider
// .getNewClientTransaction(request);
// Send the request statefully, through the client transaction.
// transaction.sendRequest();
}
}
Call it From SipManager class as
public void disconnectCall() throws NotInitializedException {
// TODO Auto-generated method stub
if (!initialized)
throw new NotInitializedException("Sip Stack not initialized");
this.sipManagerState = SipManagerState.BYE;
Bye byeRequest = new Bye();
Request r=null ;
try{
r = byeRequest.MakeRequest(this);//byeRequest.MakeRequest(SipManager.this);
final ClientTransaction transaction = this.sipProvider
.getNewClientTransaction(r);
Thread thread = new Thread() {
public void run() {
try {
transaction.sendRequest();
} catch (SipException e) {
e.printStackTrace();
}
}
};
thread.start();
} catch (TransactionUnavailableException e) {
e.printStackTrace();
}catch (InvalidArgumentException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
}
I have got 481 error code as response.I think I have missed the current callid field in the bye message.I have searched for it but not found from sipmanager class.pls help.
Nidhin,
BYE messages are always inside a SIP dialog, so you don't have to create a new message from scratch. Instead, you just need to get ahold of the dialog you want to terminate, create a request of type BYE from that and send it. JAIN will take care of the rest.
For an example, you can check the code at the Mobicents restcomm-android-sdk repo, method sendByeClient():
https://github.com/Mobicents/restcomm-android-sdk/blob/master/sipua/src/main/java/org/mobicents/restcomm/android/sipua/impl/SipManager.java#L931
Please also keep in mind that the JAIN SIP example has been obsoleted by Messenger example that uses the Restcomm Android Client SDK which offers a simpler API. Here's its code for your reference:
https://github.com/Mobicents/restcomm-android-sdk/tree/master/Examples/restcomm-messenger