Android 8中StaxXmlPullParserFactory实例化方法及XMPP连接崩溃问题求助
Hey there! Let's break down and solve your two Android technical issues step by step:
StaxXmlPullParserFactory on Android 8 (API 26) Android 8 and later versions removed the standard Java EE StAX APIs (like javax.xml.stream.XMLInputFactory) from the system classpath. Since org.jivesoftware.smack.xml.stax.StaxXmlPullParserFactory depends on these APIs, you can't instantiate it directly without adding compatible libraries first:
- First, add these dependencies to your app-level
build.gradle(Module level) to include the StAX API and a reliable implementation (Woodstox is a widely used choice):dependencies { // StAX API dependency implementation 'javax.xml.stream:stax-api:1.0-2' // Woodstox implementation for StAX implementation 'com.fasterxml.woodstox:woodstox-core:6.5.1' } - Then, you can either let Smack's ServiceLoader auto-detect the factory (after adding dependencies) or explicitly initialize it:
try { StaxXmlPullParserFactory factory = new StaxXmlPullParserFactory(); XmlPullParser parser = factory.newXmlParser(); // Use the parser for your XML processing needs } catch (XmlPullParserException e) { e.printStackTrace(); }
Looking at your crash log, the root cause is unambiguous:
java.lang.ClassNotFoundException: Didn't find class "javax.xml.stream.XMLInputFactory"
This ties directly to the missing StAX dependencies we covered above. Here's a complete fix, including critical adjustments to your code:
Step 1: Add Required Dependencies
Add the StAX API and Woodstox dependencies to your build.gradle as shown in the first issue.
Step 2: Revise Your XMPPHandler Class
Your current XMPPHandler inherits from AppCompatActivity—this is unnecessary, as it's a utility class for XMPP connections, not a UI component. Additionally, network operations like connect() must never run on the main thread (Android blocks main-thread network calls to avoid UI freezing). Here's the cleaned-up code:
import android.content.Context; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.android.AndroidSmackInitializer; import org.jivesoftware.smack.tcp.XMPPTCPConnection; import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration; import org.jxmpp.stringprep.XmppStringprepException; import java.io.IOException; // Convert to a regular utility class instead of an Activity public class XMPPHandler { private XMPPTCPConnection connection; public void connect(Context context) { // Run network logic on a background thread new Thread(() -> { try { // Initialize Smack for Android first AndroidSmackInitializer.initialize(context); XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder() .setXmppDomain("192.168.1.9") .setHost("192.168.1.9") .setPort(5222) .setSecurityMode(XMPPTCPConnectionConfiguration.SecurityMode.ifpossible) // Disable hostname verification for testing with IP addresses .setHostnameVerifier((hostname, session) -> true) .build(); connection = new XMPPTCPConnection(config); connection.connect(); // Optional: Call login here if needed // login("your-username", "your-password"); } catch (IOException | InterruptedException | XMPPException | SmackException | XmppStringprepException e) { e.printStackTrace(); } }).start(); } public void login(String username, String password) throws XMPPException, InterruptedException, IOException, SmackException { if (connection != null && connection.isConnected()) { connection.login(username, password); } } // Add a method to clean up connections when done public void disconnect() { if (connection != null && connection.isConnected()) { connection.disconnect(); } } }
Step 3: Ensure Proper Smack Initialization
Create or update your Application class to initialize Smack and explicitly set the parser factory, avoiding ServiceLoader inconsistencies:
import android.app.Application; import org.jivesoftware.smack.android.AndroidSmackInitializer; import org.jivesoftware.smack.xml.SmackXmlParser; import org.jivesoftware.smack.xml.stax.StaxXmlPullParserFactory; import org.xmlpull.v1.XmlPullParserException; public class MyApp extends Application { @Override public void onCreate() { super.onCreate(); AndroidSmackInitializer.initialize(this); // Explicitly set the StAX parser factory to avoid loading issues try { SmackXmlParser.setXmlPullParserFactory(new StaxXmlPullParserFactory()); } catch (XmlPullParserException e) { e.printStackTrace(); } } }
Don't forget to register this MyApp class in your AndroidManifest.xml:
<application android:name=".MyApp" ...> <!-- Your activities and services go here --> </application>
内容的提问来源于stack exchange,提问作者Salman Farid

