XMPP手机上Android无法连接PC上的OpenFire的解决方案

    xiaoxiao2025-02-04  11

    这几天由于要做一个解决方案,才来学XMPP方案,Android+Smack+Openfire方案,其实这已经是很成熟的方案了。但因为没做过,所以有必要总结一下:

    第一,PC的问题,很容易,也很快。只要解决防火墙的问题就可以解决了。示例代码如下:

    1、GlobalHelper.java类

    import org.jivesoftware.smack.Connection; import org.jivesoftware.smack.ConnectionConfiguration; import org.jivesoftware.smack.PacketCollector; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Registration; public class GlobalHelper { private static Connection con; private static String Service_Name="www.example.com"; public static Connection CreateConnection() { // Create the configuration for this new connection XMPPConnection.DEBUG_ENABLED=false; ConnectionConfiguration config = new ConnectionConfiguration("172.168.1.100", 5222); config.setCompressionEnabled(false); config.setSASLAuthenticationEnabled(false); System.out.println("T1"); if(con==null||con.isConnected()==false) { try { con=new XMPPConnection(config); System.out.println("T2"); con.connect(); System.out.println("T3"); return con; } catch(XMPPException e) { System.out.println("T4"); System.out.println(e.getMessage()); e.printStackTrace(); return null; } } return con; } }

    2、testopenfire.java类

    import java.io.File; import java.util.Collection; import org.jivesoftware.smack.Connection; import org.jivesoftware.smack.RosterEntry; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smackx.filetransfer.FileTransfer; import org.jivesoftware.smackx.filetransfer.FileTransferManager; import org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer; public class testopenfire { public static void main(String[] args) throws Exception { // TODO Auto-generated method stub String account="test"; String password="test"; String retStr=Register(account, password); if(retStr=="0") System.out.println("fail"); else System.out.println("success"); getFriends(GlobalHelper.CreateConnection()); sendMessage("test1@example.com","我的测试数据",GlobalHelper.CreateConnection()); SendFile(GlobalHelper.CreateConnection(),"test1@example.com"); } public static String Register(String account,String password) { Connection conn=GlobalHelper.CreateConnection(); if(conn==null) return "0"; if(conn.isConnected()==false) return "0"; try { System.out.println( "连接成功"); conn.login(account, password); System.out.println("登录成功"); return "1"; } catch(XMPPException e) { System.out.println("登录失败:"+e.getMessage()); return "0"; } } public static boolean sendMessage(String JID,String body,Connection connection) { System.out.println("发送消息开始。。。。。"); Message newmsg=new Message(); newmsg.setTo(JID); newmsg.setBody(body); newmsg.setType(Message.Type.normal); try { connection.sendPacket(newmsg); System.out.println("发送消息结束。。。。。成功!"); return true;   } catch(Exception e) { System.out.println("发送消息结束。。。。。失败!"); return false; } } public static void getFriends(Connection connection) { System.out.println("获取好友列表"); Collection<RosterEntry> rosters=connection.getRoster().getEntries(); for(RosterEntry rosterEntry:rosters) { System.out.println("name:"+rosterEntry.getName()+",jid:"+rosterEntry.getUser()); } } public static void SendFile(Connection connection,String User) throws Exception { System.out.println("进入发送文件方法。。。"+User); Presence pre=connection.getRoster().getPresence(User); System.out.println(pre); if(pre.getType()!=Presence.Type.unavailable) { FileTransferManager manager=new FileTransferManager(connection); OutgoingFileTransfer transfer=manager.createOutgoingFileTransfer(pre.getFrom()); transfer.sendFile(new File("test.png"), "图片"); while(!transfer.isDone()) { if(transfer.getStatus()==FileTransfer.Status.in_progress) { System.out.println(transfer.getStatus()); System.out.println(transfer.getProgress()); System.out.println(transfer.isDone()); } } } } } 以上是PC上的问题,如果连不上,基本都是防火墙的事。只要连不上,把防火墙关了就行了。

    第二,就是Android手机或模拟器的问题了。这个问题经常出现如下三类错误,但网上又找不到,问又没解决方案。下面就我碰到的提出解决方案:

    前提条件:

    PC(或笔记本,无线或有线都可以,全试过)->路由<-手机(无线)

    具体方案:

    1、PC防火墙的问题,关闭就行了。

    2、解决网络是否通的问题。在手机或模拟器上安装FPing ,解决Ping我PC地址是否通的问题,下载Easy Telnet解决端口5222(默认)是否通的问题。如果不通就得检查一下哪里出了问题。另外得从PC解决Ping我的手机的问题。获取手机IP的问题有如下几种方法:

    1)自己写一个程序,获取本地IP。

    2)网上随便下载一个获取本地IP的软件,N多,非常容易。

    3)从路由上获取IP

    以上这些都比较容易从PC Ping手机IP。通过以上的方法解决手机和电脑网络没问题。

    3、以上确认完后,然后就是Android的问题了。

    1)确认你的程序没问题,不同Smack版本,写法都是对应版本的写法,最简单的办法都是下载版本文档中都有一个对应的示例代码,各种参数设置是正确的。

    2)第1)种情况都没问题的情况下,出现如下错误:

    XMPPError connecting to 172.168.1.100:5222.: remote-server-error(502) XMPPError connecting to 172.168.1.100:5222.   -- caused by: java.net.SocketException: socket failed: EACCES (Permission denied)

    这个问题的解决方案,在AndroidManifest.xml中加入如下代码就行了:

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>     <uses-permission android:name="android.permission.INTERNET"/>     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    前两条语句最重要。

    3)就是解决Android的Bug问题(这是我个人的理解,已经N年了Google还是没解决这个问题),出现的问题如下:

    java.lang.IllegalArgumentException: Can't initialize the configured debugger!

    这个问题之前我有关在讲网络编程时好象讲过。只要将如下的语句加进来就可以了。具体如下:

    StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build());   StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().detectLeakedClosableObjects() .penaltyLog().penaltyDeath().build());  

    这个问题已经不是问题了,做Android网络编程的人(游戏、网购等的)非常熟悉。但对于初学者,没有愿意帮介绍。我今天总结一下,给大家发出来。我查过一天,翻墙等都没解决这个问题。没办法,一直在试,当快抢劫信心时,发现了问题所在。

    全部原码如下,不通再找我:

    package com.example.xmppclient; import org.jivesoftware.smack.Connection; import org.jivesoftware.smack.ConnectionConfiguration; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.StrictMode; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class LoginActivity extends Activity { private Button btnLogin; private Button btnExit; private EditText txtUserID; private EditText txtPWD; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()          .detectDiskReads().detectDiskWrites().detectNetwork()          .penaltyLog().build());   StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()          .detectLeakedSqlLiteObjects().detectLeakedClosableObjects()          .penaltyLog().penaltyDeath().build());   setContentView(R.layout.login); btnLogin=(Button)findViewById(R.id.btnLogin); btnExit=(Button)findViewById(R.id.btnExit); txtUserID=(EditText)findViewById(R.id.txtUserID); txtPWD=(EditText)findViewById(R.id.txtPWD); btnLogin.setOnClickListener(new OnClickListener(){ public void onClick(View v) { //XMPPConnection.DEBUG_ENABLED=true; try { ConnectionConfiguration config = new ConnectionConfiguration("172.168.1.100", 5222); config.setCompressionEnabled(false); config.setSASLAuthenticationEnabled(false); Connection conn2 = new XMPPConnection(config); conn2.connect(); String account=txtUserID.getText().toString(); String password=txtPWD.getText().toString(); conn2.login(account, password); //Toast.makeText(getApplicationContext(),"登录成功", 5000).show(); Intent intent=new Intent(LoginActivity.this,MainActivity.class); startActivity(intent); } catch(XMPPException e) { Toast.makeText(getApplicationContext(), e.getMessage(), 5000).show(); } catch(Exception ex) { Toast.makeText(getApplicationContext(), ex.getMessage(), 5000).show(); } }}); btnExit.setOnClickListener(new OnClickListener(){ public void onClick(View v) { LoginActivity.this.finish(); }}); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.login, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }

    XML文件如下:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:tools="http://schemas.android.com/tools"     android:id="@+id/LinearLayout1"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:orientation="vertical"     android:paddingBottom="@dimen/activity_vertical_margin"     android:paddingLeft="@dimen/activity_horizontal_margin"     android:paddingRight="@dimen/activity_horizontal_margin"     android:paddingTop="@dimen/activity_vertical_margin"     tools:context="com.example.xmppclient.LoginActivity" >     <LinearLayout         android:layout_width="match_parent"         android:layout_height="wrap_content" >         <TextView             android:id="@+id/textView1"             android:layout_width="wrap_content"             android:layout_height="wrap_content"             android:text="TextView" />         <EditText             android:id="@+id/txtUserID"             android:layout_width="wrap_content"             android:layout_height="wrap_content"             android:layout_weight="1"             android:text="test"             android:ems="10" >             <requestFocus />         </EditText>     </LinearLayout>     <LinearLayout         android:layout_width="match_parent"         android:layout_height="wrap_content" >         <TextView             android:id="@+id/textView2"             android:layout_width="wrap_content"             android:layout_height="wrap_content"             android:text="TextView" />         <EditText             android:id="@+id/txtPWD"             android:layout_width="wrap_content"             android:layout_height="wrap_content"             android:layout_weight="1"             android:ems="10"             android:text="test"             android:inputType="textPassword" />     </LinearLayout>     <LinearLayout         android:layout_width="match_parent"         android:layout_height="wrap_content" >         <Button             android:id="@+id/btnLogin"             android:layout_width="wrap_content"             android:layout_height="wrap_content"             android:text="Login" />         <Button             android:id="@+id/btnExit"             android:layout_width="wrap_content"             android:layout_height="wrap_content"             android:text="Exit" />     </LinearLayout> </LinearLayout>

    转载请注明原文地址: https://ju.6miu.com/read-1296095.html
    最新回复(0)