public synchronized void sendFile(final String fileName,
            final long fileSize, final String description,
            final NegotiationProgress progress) {
        if (progress == null) {
            throw new IllegalArgumentException("Callback progress cannot be null.");
        }
        checkTransferThread();
        if (isDone() || outputStream != null) {
            throw new IllegalStateException(
                    "The negotiation process has already"
                            + " been attempted for this file transfer");
        }
        setFileInfo(fileName, fileSize);
        this.callback = progress;
        transferThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    OutgoingFileTransfer.this.outputStream = negotiateStream(
                            fileName, fileSize, description);
                    progress.outputStreamEstablished(OutgoingFileTransfer.this.outputStream);
                }
                catch (XMPPErrorException e) {
                    handleXMPPException(e);
                }
                catch (Exception e) {
                    setException(e);
                }
            }
        }, "File Transfer Negotiation " + streamID);
        transferThread.start();
    }
public synchronized void sendFile ( final String fileName , final long fileSize , final String description , final NegotiationProgress progress ) { if ( progress == null ) { throw new IllegalArgumentException ( "Callback progress cannot be null." ) ; } checkTransferThread ( ) ; if ( isDone ( ) || outputStream != null ) { throw new IllegalStateException ( "The negotiation process has already" + " been attempted for this file transfer" ) ; } setFileInfo ( fileName , fileSize ) ; this . callback = progress ; transferThread = new Thread ( new Runnable ( ) { @ Override public void run ( ) { try { OutgoingFileTransfer . this . outputStream = negotiateStream ( fileName , fileSize , description ) ; progress . outputStreamEstablished ( OutgoingFileTransfer . this . outputStream ) ; } catch ( XMPPErrorException e ) { handleXMPPException ( e ) ; } catch ( Exception e ) { setException ( e ) ; } } } , "File Transfer Negotiation " + streamID ) ; transferThread . start ( ) ; }
This methods handles the transfer and stream negotiation process. It
returns immediately and its progress will be updated through the
{@link NegotiationProgress} callback.

@param fileName
The name of the file that will be transmitted. It is
preferable for this name to have an extension as it will be
used to determine the type of file it is.
@param fileSize
The size in bytes of the file that will be transmitted.
@param description
A description of the file that will be transmitted.
@param progress
A callback to monitor the progress of the file transfer
negotiation process and to retrieve the OutputStream when it
is complete.