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

来源:互联网 发布:银联数据2017offer待遇 编辑:程序博客网 时间:2024/05/22 13:19

这几天由于要做一个解决方案,才来学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>

0 1