File transfer using Smack 4.2.3 gives service-unavailable error - android

I’m developing XMPP client using smack 4.2.3. Using ejabberd as an XMPP server on linux platform.
Using following code to send file:
public static void sendFile(String path, String description){
String sFqdn = currentUser.getFqdn();
if(sFqdn.equals(null)) return;
String node = XmppStringUtils.parseLocalpart(sFqdn);
String domain = XmppStringUtils.parseDomain(sFqdn);
String resource = XmppStringUtils.parseResource(sFqdn);
try {
EntityFullJid fqdn = entityFullFrom(node, domain, resource);
OutgoingFileTransfer transfer = FileTransferManager.getInstanceFor(connection).createOutgoingFileTransfer(fqdn);
transfer.sendFile(new File(path), description);
} catch (SmackException e) {
e.printStackTrace();
} catch (XmppStringprepException e) {
e.printStackTrace();
}
}
and to receive:
if(fileTransferManager == null){
fileTransferManager = FileTransferManager.getInstanceFor(connection);
fileTransferManager.addFileTransferListener(new FileTransferListener() {
#Override
public void fileTransferRequest(final FileTransferRequest request) {
// Accept it
IncomingFileTransfer transfer = request.accept();
try {
transfer.recieveFile(new File(dir_path+request.getFileName()));
} catch (SmackException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
});
}
sometimes it successfully sends a file between users, but most of the time i get this XMPP error:
D/SMACK: RECV (1): <iq xml:lang=‘en’ to=‘bob#domain/122573506394002920791746’ from=‘tom#domain/126676407739368221821682’ type=‘set’ id=‘VdzEA-77’><si xmlns=‘http: //jabber .org/protocol/si’ id=‘jsi_8874207690796615693’ mime-type=‘image/png’ profile=‘http ://jabber .org/protocol/si/profile/file-transfer’><desc>test file</desc></file><feature xmlns=‘http ://jabber .org/protocol/feature-neg’><x xmlns=‘jabber:x:data’ type=‘form’><field var=‘stream-method’ type=‘list-single’><option><value>http ://jabber .org/protocol/bytestreams</value></option><option><value>http ://jabber .org/protocol/ibb</value></option></field></x></feature></iq><r xmlns=‘urn:xmpp:sm:3’/>
D/SMACK: SENT (1): <iq to=‘tom#domain/126676407739368221821682’ id=‘VdzEA-77’ type=‘error’><error type=‘cancel’><service-unavailable xmlns=‘urn:ietf:params:xml:ns:xmpp-stanzas’/></error></iq>
In ejabberd config file I’ve successfully enabled the module “mod_proxy65”
One reason I can think of is that it might happening due to continuous presence changed by the receiver, that changes its resource.
Although I’m keeping the track of presence in Roster’s presenceChanged() method but still no success. I’m wondering if there is any way in smack to connect to server with a static resource?
One more thing, is there any example for HTTP_FILE_UPLOAD (XEP-0363), I can’t find any in smacks official documentation.

After discussion at ignite realtime's forum, I found out that I was hitting a bug.
A work around to this bug is forced in-band byte stream.
Setting FileTransferNegotiator.IBB_ONLY to true did the trick for me.
Please take a look at line 76 in FileTransferNegotiator class as well.

Related

how to get chat history from xmpp server smack library

I want to get chat history for one to one chat and group chat. after some research i came to know that i can do it by Message Archive Management . but it does not provide any example to get older message in to android client. i want to get older message chat history from server, but i dont know how to pull older messages from xmpp server. there are so many questions asked about this over here but didn't get any proper solution. what i have done till now is connection and sending message to other user. can anyone help me to get history of chat from xmpp server?
XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()
.setUsernameAndPassword("user1", "password")
.setHost(getString(R.string.domain))
.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)
.setServiceName(getString(R.string.domain))
.setPort(5222)
.setDebuggerEnabled(true) // to view what's happening in detail
.build();
XMPPTCPConnection conn1 = new XMPPTCPConnection(config);
conn1.setUseStreamManagement(true);
XMPPTCPConnection.setUseStreamManagementDefault(true);
conn1.setUseStreamManagementResumption(true);
// ReconnectionManager.getInstanceFor(this.conn1).enableAutomaticReconnection();
conn1.setPacketReplyTimeout(10000);
try {
conn1.connect();
if(conn1.isConnected()) {
Log.w("app", "conn done");
}
conn1.login();
if(conn1.isAuthenticated()) {
Log.w("app", "Auth done");
}
}
catch (Exception e) {
Log.w("app", e.toString());
}
ChatManager chatmanager = ChatManager.getInstanceFor(conn1);
Chat newChat = chatmanager.createChat("user2#"+getString(R.string.domain));
try {
newChat.sendMessage("Test Msg from user1!!!");
}
catch (SmackException.NotConnectedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
I'd use Smack's MamManager. For example MamManager.queryArchive(Integer).

Function chatDidReceiveMessage not working Quickblox

I use this framework to create a messenger on Android and iOS.
In android I create a message and send it.
The server quickblox it comes !
I also see this message in the log of xcode... but no further response should not be, because the function - (void)chatDidReceiveMessage:(QBChatMessage *)message is break point.
What am I doing wrong?
Code for sending message(Android)
// create a message
QBChatMessage chatMessage = new QBChatMessage();
chatMessage.setProperty("save_to_history", "1"); // Save a message to history
chatMessage.setBody("Hi there");
chatMessage.setDateSent(new Date().getTime()/1000);
// attach a audio
QBAttachment attachment = new QBAttachment("audio");
attachment.setId(file.getId().toString());
chatMessage.addAttachment(attachment);
try {
currentChatRoom.sendMessage(chatMessage);
} catch (XMPPException e) {
e.printStackTrace();
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
}
Code in log XCode
2015-12-13 16:05:27.638 Messenger[462:5623] [ChatService] Message RCV: <message xmlns="jabber:client" id="566d5efb1fecfa062778dcd9" to="6804658-31081#chat.quickblox.com/A9320123-BD0A-4C80-BD81-F729D036877A" type="groupchat" from="31081_56616b87a0eb4756f2000b6d#muc.chat.quickblox.com/6919398"><body>Hi there</body><extraParams xmlns="jabber:client"><attachment type="audio" id="3173128"/><date_sent>1450011927</date_sent><save_to_history>1</save_to_history><message_id>566d5efb1fecfa062778dcd9</message_id><dialog_id>56616b87a0eb4756f2000b6d</dialog_id></extraParams><delay xmlns="urn:xmpp:delay" stamp="2015-12-13T13:05:27Z"/></message>
I don't understand((
If I am right, you send messages to chat room (not private chat), and then you should use chatRoomDidReceiveMessage:fromDialogID: instead. I faced the same problem, described in chatDidReceiveMessage: not called post.

Android autobahn WebSockets connection lost when connection with dialogic xms

I am trying to connect to dialogic xms server using autobahn WebSockets:
As read I need to add a protocol rtcweb
This is my code :
String uri = "ws://myUrl:port";
WebSocketConnection ws = new WebSocketConnection();;
wsObserver = new WebSocketObserver();
String[] protocols = {"rtcweb"};
try {
ws.connect(new URI(uri), protocols, wsObserver, new WebSocketOptions() );
} catch (WebSocketException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
}
But when i add the protocol rtcweb I get this onClose; and the connection still didn't open :
Code: CONNECTION_LOST. Reason: WebSockets connection lost

Android Serversocket does not seem to accept connections on emulators

I've been trying to implement a simple socket communication between two Android emulators but just can't seem to get it.
My server:
public void run() {
if (SERVERIP != null) {
try {
serverStatus.setText("My IP: " + SERVERIP);
serverSocket = new ServerSocket(6798);
serverStatus.setText("ServerSocket Created");
}
catch(Exception e) {
e.printStackTrace();
}
try {
while (true) {
serverStatus.setText("waiting for client");
Socket client = serverSocket.accept();
serverStatus.setText("Connected.");
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String line = in.readLine();
serverStatus.setText(line);
in.close();
client.close();
}
}
catch(Exception e) {
e.printStackTrace();
}
}
else
serverStatus.setText("Couldn't detect internet connection.");
}
My Client:
try {
InetAddress ina = InetAddress.getByName("10.0.2.2");
socket = new Socket(ina, 6789);
}
catch (Exception e) {
e.printStackTrace();
}
try {
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
out.println("Hey Server!");
dispText.setText("sent");
}
catch (Exception e) {
e.printStackTrace();
}
The Client side goes on to display the message "sent" however the Server does not move beyond "waiting for client" (stuck on the blocking accept()).
I've used telnet on my Windows machine to redirect port 6789 to 6798 on the server emulator's console. I've also tried turning off my firewall and the other suggestions posted on the similar questions asked here. Please help as just can't seem to get it and feel like I'm making a very stupid mistake.
Also, can anyone please tell me how it is possible for the Client to move beyond the Socket creation code line if the Server is still stuck on accept(). Or, does it not matter to the client that the Server isn't responding as long as it is listening on the port??
Android emulators are placed behind a virtual firewall/router by design, and cannot see each other, even when they are on the same network. The "Using Network Redirection", as well as "Interconnecting Emulator Instances" part of Google's doc on the emulator explains how to communicate with an emulator instance.
As for your last question. Use the empty constructor for socket, and then use the connect call with a specified timeout.

How to accept bluetooth received file in Android application?

I would like to implement an application to receive a file from a Bluetooth device.
Before receiving, a notification will be raised to accept an incoming file request.
From there, i would like to activate "accept" and download the file automatically without raising an accept dialog when the user receive a second file from another Bluetooth paired device, without notification disturbance when the user launchs an application.
I developed an app that include this kind of task, and you can use BluetoothChat example.
You must set the secure flag to false:
`
boolean secure = false;
try {
if (secure) {
tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE,
MY_UUID_SECURE);
} else {
tmp = mAdapter.listenUsingInsecureRfcommWithServiceRecord(
NAME_INSECURE, MY_UUID_INSECURE);
}
} catch (IOException e) {
Log.e(TAG, "Socket Type: " + mSocketType + "listen() failed", e);
mmServerSocket = tmp;
}`
And then read the buffer from the InputStream that you can find in ConnectedThread:
while (true) {
try {
bytes = mmInStream.read(buffer);
/*write bytes in a file*/
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
BluetoothChatService.this.start();
break;
}
}
You can try using the Bluetooth socket connection to set a client server TCP like connection.
ON ROOTED DEVICES, You can just install only two apps on your phone to achieve your goal.
XPosed Installer
Auto-Accept
This way you hook System service.
import android.util.*;
import de.robv.android.xposed.*;
import de.robv.android.xposed.callbacks.XC_LoadPackage.*;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
public class Tutorial implements IXposedHookLoadPackage
{
private String TAG="TUTORIAL";
public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
if (!lpparam.packageName.equals("com.android.bluetooth"))
{
Log.i(TAG,"Not: "+lpparam.packageName);
return;
}
Log.i(TAG,"Yes "+lpparam.packageName);
findAndHookMethod("com.android.bluetooth.opp.BluetoothOppManager", lpparam.classLoader, "isWhitelisted", String.class,new XC_MethodHook() {
#Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
Log.v(TAG,"HOOK DONE");
param.setResult(true); /* you can compare the sender address(String) with your computer and determine if you return true or just allow the original method to be called after this returns.*/
}
});
}
}
For more information, please visit my answer in SO.
I'll post some direct links here.
Links
Dropbox link of the auto accepting app
Dropbox link of the project files (zip)
Xposed apk site
Towelroot site to root your phone
Auto-Accept github repository

Categories

Resources