Real solution to File Transfer Using XMPP Asmack
In the process of using Asmack, file transmission is a huge obstacle that hinders me from moving forward. Baidu and Google cannot be resolved. By accident, I suddenly looked back and solved this problem. Therefore, set this post to record for yourself, and hope to help the Later users. I hope that I can make the same instant communication and send various rich media. Next I will see how to implement file transmission.
First, version problems. <喎?http: www.bkjia.com kf ware vc " target="_blank" class="keylink"> Vc3ryb25np1_vcd4kpha + QXNtYWNrysfSu7j2v6rUtL/release/m/release + release/UdyYWlsyKW5ub2oo6y2 + release/release Authorization + authorization/ew5rG + authorization + cve-vcd4kpha + PHN0cm9uZz612rb + signature + PC9wPgo8cD65 + signature/KOsyLu688v509C1xL/JsunXysHP O6zM + dfTo6y7 + bG + us3V4rj2z + release + NHUz + release + zb/release + tfZoaM8L3A + release + PGJyPgo8L3A + release + 1eLKx7j0 Signature + dTatcS12Le9oaM8L3A + signature + NDQxr3MqLXEs/Signature + 087zSy/Signature + signature + ssystPrC66Gjz + rPuLXEuf2zzLrNvLzK9c + Signature ZabE0bXEoaM8L3A + cjxwp1_vcd4kphbyzsbjbgfzcz0 = "brush: java;"> public class SanLiaoApplication extends Application {private List activityList = new shortlist (); private SmackAndroid smackAndroid SmackAndroid; // The public void onCreate () {super. onCreate (); // use log4j to enable LogConfigurator logConfigurator = new LogConfigurator (); SimpleDateFormat sDateFormat = new SimpleDateFormat ("yyyy-MM-dd hh: mm: ss" ); Java. util. date date = new java. util. date (); String dateString = date. getYear () + "_" + (date. getMonth () + 1) + "_" + date. getDate () + "_" + date. getHours () + "_" + date. getMinutes () + "_" + date. getSeconds (); String pathString = Environment. getExternalStorageDirectory () + File. separator + "sanliao" + File. separator + "logs" + File. separator + "sanliao" + dateString + ". log "; Log. d ("EIM", pathString); logConfigurator. setFileName (pathString ); LogConfigurator. setRootLevel (Level. DEBUG); logConfigurator. setLevel ("org. apache ", Level. ERROR); logConfigurator. setFilePattern ("% d % t %-5 p [% c {2}]-[% L] [% M] % m % n"); logConfigurator. setMaxFileSize (1024*1024*5); logConfigurator. setImmediateFlush (true); logConfigurator. configure (); Logger logger = Logger. getLogger (EimApplication. class); logger.info ("eim app is created info"); logger. debug ("eim app is creatd Ebug "); logger. error ("eim app is create error"); smackAndroid = SmackAndroid. init (getApplicationContext (); // It is required to initialize the Asmack platform. Otherwise, the iterm not find (404) error will occur in the subsequent transmission files. XMPPConnection. DEBUG_ENABLED = true; logger. debug ("XMPPConnectionDebug enable");} // Add Activity to the container public void addActivity (Activity activity) {activityList. add (activity);} // traverse all activities and finishpublic void exit () {XmppConnectionManager. getInstance (). disconnect (); smackAndroid. onDestroy (); for (Activity activity: activityList) {activity. finish ();}}}
The above code mainly includes three parts: 1) initialize the log4j log system; 2) initialize the Asmack platform; 3) put all the activities in a list, which is mainly used to manage the Activity, it can be used for exit and other processing.
2) initialize FileTransferManager
This step can be found on the Internet. However, it is important to note that, in at least 0.8.1.1, the code on the Internet usually keeps you running.
First look at the code.
// If you need transport file. you need call this method after connect and loginpublic boolean initFileTransport () {if (connection = null) {return false;} else if (fileTransferManager! = Null) {return true;} else {// fileTransferManager = new FileTransferManager (connection); // put it here on the Internet. This causes Asmack to crash ServiceDiscoveryManager sdManager = ServiceDiscoveryManager. getInstanceFor (connection); if (sdManager = null) {sdManager = new ServiceDiscoveryManager (connection);} sdManager. addFeature ("http://jabber.org/protocol/disco#info"); sdManager. addFeature ("jabber: iq: privacy"); FileTransferNegotiator. setService Enabled (connection, true); fileTransferManager = new FileTransferManager (connection); // This is true in version 0.8.1.1 (later. Return true ;}}
I encapsulate initialization in a function. Three reminders are required:(1) The order in the above Code is generally different from that on the Internet;
(2) I use fileTransferManager as a member of XMPPConnection. The reason why I changed this is that connection is global, and you can do so on your other global (at least the life cycle is basically synchronous with the APP), rather than the XMPPConnect code. Therefore, this is a design issue.
(3) This function must be called after login logs in.
In order to give you a complete context, I am still very careful about the login code.
// Log on to private Integer login () {String username = loginConfig. getUsername (); String password = loginConfig. getPassword (); Log. d (LOG_TAG, "login now"); try {XMPPConnection connection = XmppConnectionManager. getInstance (). getConnection (); Log. d (LOG_TAG, "login c2"); logger. debug ("XMPPConnection create"); connection. connect (); logger. debug ("XMPPConnection connected"); Log. d (LOG_TAG, "login c3"); logger. debug ("username:" + username + ", passwd:" + password); connection. login (username, password); // log on to logger. debug ("XMPPConnection logined"); // init the file transport can not put it hereXmppConnectionManager. getInstance (). initFileTransport (); // file transfer management initialization // OfflineMsgManager. getInstance (activitySupport ). dealOfflineMsg (connection); // process offline message connection. sendPacket (new Presence (Presence. type. available); Log. d (LOG_TAG, "login c5"); if (loginConfig. isNovisible () {// stealth login Presence presence = new Presence (Presence. type. unavailable); Collection
Rosters = connection. getRoster (). getEntries (); for (RosterEntry rosterEntry: rosters) {presence. setTo (rosterEntry. getUser (); connection. sendPacket (presence) ;}} loginConfig. setUsername (username); if (loginConfig. isRemember () {// Save the password loginConfig. setPassword (password);} else {loginConfig. setPassword ("");} loginConfig. setOnline (true); return Constant. LOGIN_SECCESS;} catch (Exception xee) {Log. d (LOG_TAG, xe E. toString (); if (xee instanceof XMPPException) {XMPPException xe = (XMPPException) xee; Log. d (LOG_TAG, xe. toString (); final XMPPError error = xe. getXMPPError (); int errorCode = 0; if (error! = Null) {errorCode = error. getCode () ;}if (errorCode = 401) {return Constant. LOGIN_ERROR_ACCOUNT_PASS;} else if (errorCode = 403) {return Constant. LOGIN_ERROR_ACCOUNT_PASS;} else {return Constant. SERVER_UNAVAILABLE ;}} else {return Constant. LOGIN_ERROR ;}}}
At this point, the initialization work has come to an end. Now, the next step is how to implement transmission.3) sender.
Send an image as an example.
As shown in, we hope that when we click "image", we can select an image. After selecting an image, we can send it out. I believe that this is what we need. After all, this is the same.
First, the "image" control needs to respond to the click.
////// Transport image buttontupianBtn = (ImageButton) getActivity (). findViewById (R. id. imageButton_tupian); tupianBtn. setOnClickListener (new OnClickListener () {@ Overridepublic void onClick (View v) {// TODO Auto-generated method stub Toast. makeText (getActivity (), "send file", Toast. LENGTH_SHORT ). show (); Intent intent = new Intent (); intent. setType ("image/*"); // select the image, which uses the system intent. Intent. setAction (Intent. ACTION_GET_CONTENT); startActivityForResult (intent, TUPIAN_RESULT); // return to the Activity after the selection. }});
After the image is selected, the Activity is returned. Therefore, we will process it as follows.
Public void onActivityResult (int requestCode, int resultCode, Intent data) {if (requestCode = TUPIAN_RESULT) {Uri uri = data. getData (); String [] proj = {MediaStore. images. media. DATA}; Cursor cursor = getActivity (). managedQuery (uri, proj, null); int index = cursor. getColumnIndexOrThrow (MediaStore. images. media. DATA); cursor. moveToFirst (); String img_path = cursor. getString (index); Log. d ("FragMultiFunc", "img_path : "+ Img_path); String toId = (AChatActivity) getActivity ()). getTo (); new sendfiletask(cmd.exe cute (img_path, toId); // The image path and who I want to send it .}}
Right, open an AsynCTask to send the image, and transmit two parameters to the task. The path of the image file and who I want to send it. Next, I will show you all the code for SendFileTask.Public class SendFileTask extends AsyncTask
{Private final static Logger logger = Logger. getLogger (SendFileTask. class); private final static String TAG = "SendFileTask"; @ Overrideprotected Integer doInBackground (String... params) {// TODO Auto-generated method stub if (params. length <2) {Log. d (TAG, "parameter invalide"); return Integer. valueOf (-1);} String img_path = params [0]; String toId = params [1] + "/Smack"; Log. d (TAG, "img_path:" + img_path); logge R. debug ("img_path:" + img_path); // XmppConnectionManager. getInstance (). initFileTransport (); FileTransferManager fileTransferManager = XmppConnectionManager. getInstance (). getFileTransferManager (); // get the file transfer management object (which is written in XMPPConnect) if (fileTransferManager = null) {Log. d (TAG, "get FileTransferManager failed"); return-1;} File filetosend = new File (img_path); if (filetosend. exists () = false) {Log. d (TAG, "f Ile: "+ img_path +" is not exist "); return-1;} Log. d (TAG, "to user:" + toId); OutgoingFileTransfer oft = fileTransferManager. createOutgoingFileTransfer (toId); // create an output file transmission object try {oft. sendFile (filetosend, "recv img"); // while (! Oft. isDone () {if (oft. getStatus (). equals (FileTransfer. status. error) {Log. e (TAG, "send failed");} else {Log. I (TAG, "status:" + oft. getStatus () + "| progress:" + oft. getProgress (); // print progress} try {Thread. sleep (1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke. printStackTrace () ;}} catch (XMPPException e1) {// TODO Auto-generated catch blocke1.printStackTrace () ;}return 0 ;}}
The above code sends our file in an AsyncTask and prints the progress every other second. (It can be passed to the UI for display later)This is the sender.
What about the receiver?
4) receiver
For the receiver, when I read the code on the Internet, the most painful thing is where the receiver's code is put. Instead of how the receiver code is written. Some people regard it as a Service. After all, acceptance is a "listener". I tried it, at least I didn't run it successfully. Maybe it was because I didn't initialize the platform at the time, but it didn't matter. I will tell you how it works. I think you can listen when you choose a friend.
So when I started chatting with my friends, I set up a file listener. Call the following init function in Oncreate.
public void init(){FragChatTitle fragChatTitle = new FragChatTitle(); getFragmentManager().beginTransaction().replace(R.id.chat_title_layout,fragChatTitle).commit(); FragChatHistory fragChatHistory=new FragChatHistory(); getFragmentManager().beginTransaction().replace(R.id.chat_history_layout,fragChatHistory).commit(); FragChatBottom fragChatBottom=new FragChatBottom(); getFragmentManager().beginTransaction().replace(R.id.chat_bottom_layout,fragChatBottom).commit(); FragMultiFunc fragMultiFunc=new FragMultiFunc(); getFragmentManager().beginTransaction().replace(R.id.chat_multifunc_layout,fragMultiFunc).hide(fragMultiFunc).commit(); ///add listener for file transport listener XMPPConnection connection = XmppConnectionManager.getInstance().getConnection(); FileTransferManager manager = XmppConnectionManager.getInstance().getFileTransferManager(); ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection); if (sdm == null) sdm = new ServiceDiscoveryManager(connection); sdm.addFeature("http://jabber.org/protocol/disco#info"); sdm.addFeature("jabber:iq:privacy"); // Create the file transfer manager FileTransferNegotiator.setServiceEnabled(connection, true); manager.addFileTransferListener(new FileTransferListener() {@Overridepublic void fileTransferRequest(final FileTransferRequest request) {Log.d("NewChatActivity","recv file");// TODO Auto-generated method stub new Thread(){ @Override public void run() { IncomingFileTransfer transfer = request.accept(); Log.d(LOG_TAG,"file_name:"+transfer.getFileName()); File mf = Environment.getExternalStorageDirectory(); String save_path= Environment.getExternalStorageDirectory()+File.separator+"Eim"+File.separator+transfer.getFileName(); File file = new File(save_path); try{ transfer.recieveFile(file); while(!transfer.isDone()) { try{ Thread.sleep(1000L); }catch (Exception e) { Log.e("NewChat", e.getMessage()); } if(transfer.getStatus().equals(Status.error)) { Log.e("ERROR!!! ", transfer.getError() +""); } if(transfer.getException() != null) { transfer.getException().printStackTrace(); } } }catch (Exception e) { Log.e("NewChatActivit", e.getMessage()); } }; }.start();} }); }
This function will be called by Oncreate of Activity. In this way, the complete Asmack file transmission can be run. The file is successfully transferred...If you have any questions, ask me.