Android 正在解析 xml 并且 AsyncTask doInBackground 方法永远不会完成
Android parsing xml and AsyncTask doInBackground method never finish
我是 Android 开发的新手,我构建了一个简单的应用程序,可以通过蓝牙从我的计算机接收 xml
文件。现在我想解析那个 xml
文件,我想用 AsyncTask
doInBackground
方法来做。所以首先在这里我 将字节写入 xml 文件
private void writeBytesToOutputStream(byte[] bytes, String path) {
File file = new File(path);
OutputStream out;
try {
if(file.exists()){
file.delete();
}
file.createNewFile();
out = new FileOutputStream(file);
out.write(bytes);
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// method that sets file and later calls execute().
xml.setFile(file);
}
这是我的内部 AsyncTask class。
public class XmlParser extends AsyncTask<Void, Void, String> {
private XmlPullParserFactory xmlFactoryObject;
private XmlPullParser myParser;
private File file;
String value;
public XmlParser() {
try {
xmlFactoryObject = XmlPullParserFactory.newInstance();
myParser = xmlFactoryObject.newPullParser();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
}
public void setFile(File file1) {
file = file1;
execute();
}
@Override
protected void onPreExecute() {
super.onPreExecute();
FileInputStream fis = null;
try {
if(file == null){
Toast.makeText(getActivity(), "NULL", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getActivity(), "NOT NULL " + file.getName(), Toast.LENGTH_LONG).show();
fis = new FileInputStream(file);
myParser.setInput(fis, null);
fis.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
}
@Override
protected String doInBackground(Void... params) {
int event;
try {
event = myParser.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {
String name = myParser.getName();
switch (event) {
case XmlPullParser.START_TAG:
break;
case XmlPullParser.END_TAG:
if (name.equals("from")) {
value = myParser.getAttributeValue(null, "value");
System.out.println("JUST FOR TEST " + value);
event = XmlPullParser.END_DOCUMENT;
}
break;
default:
break;
}
try {
event = myParser.next();
} catch (IOException e) {
e.printStackTrace();
}
}
}catch (XmlPullParserException e) {
e.printStackTrace();
}
return value;
}
@Override
protected void onPostExecute(String aVoid) {
super.onPostExecute(aVoid);
System.out.println("myEND " + aVoid);
Toast.makeText(getActivity(), "THE END!!! " + aVoid, Toast.LENGTH_LONG).show();
}
}
不知何故方法doInBackground()
永远不会完成。我花了将近四个小时试图修复它,但我找不到问题所在。我还添加了我的完整代码
public class UiFragment extends Fragment {
private static final int REQUEST_CONNECT_DEVICE_SECURE = 1;
private static final int REQUEST_ENABLE_BT = 3;
private String deviceName = null;
private BluetoothAdapter adapter = null;
//private ListView listViewConversation;
//private ArrayAdapter<String> conversationAdapter;
private Button onButton, offButton;
private BluetoothConnection connection = null;
ImageView im;
private XmlParser xml;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_ui, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
//listViewConversation = (ListView) view.findViewById(R.id.in);
onButton = (Button) view.findViewById(R.id.onButton);
offButton = (Button) view.findViewById(R.id.offButton);
im = (ImageView) view.findViewById(R.id.imageView);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
adapter = BluetoothAdapter.getDefaultAdapter();
xml = new XmlParser();
// If the adapter is null, then Bluetooth is not supported
if (adapter == null) {
FragmentActivity activity = getActivity();
Toast.makeText(activity, "Bluetooth is not available", Toast.LENGTH_LONG).show();
activity.finish();
}
}
@Override
public void onStart() {
super.onStart();
// If BT is not on, request that it be enabled.
// setupChat() will then be called during onActivityResult
if (!adapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
// Otherwise, setup the chat session
} else if (connection == null) {
setupChat();
}
}
private void setupChat() {
//conversationAdapter = new ArrayAdapter<String>(getActivity(), R.layout.message);
//listViewConversation.setAdapter(conversationAdapter);
onButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
sendCommand(1);
}
});
offButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
sendCommand(0);
}
});
// Initialize the BluetoothChatService to perform bluetooth connections
connection = new BluetoothConnection(handler);
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CONNECT_DEVICE_SECURE:
// When DeviceListActivity returns with a device to connect
if (resultCode == Activity.RESULT_OK) {
connectDevice(data);
}
break;
case REQUEST_ENABLE_BT:
// When the request to enable Bluetooth returns
if (resultCode == Activity.RESULT_OK) {
// Bluetooth is now enabled, so set up a chat session
setupChat();
} else {
// User did not enable Bluetooth or an error occurred
Toast.makeText(getActivity(), "Bluetooth not enable", Toast.LENGTH_SHORT).show();
getActivity().finish();
}
}
}
private void connectDevice(Intent data) {
// Get the device MAC address
String address = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
// Get the BluetoothDevice object
BluetoothDevice device = adapter.getRemoteDevice(address);
// Attempt to connect to the device
connection.connect(device);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.secure_connect_scan: {
// Launch the DeviceListActivity to see devices and do scan
Intent serverIntent = new Intent(getActivity(), DeviceListActivity.class);
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_SECURE);
return true;
}
}
return false;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_device_list, menu);
}
private void setStatus(CharSequence subTitle) {
FragmentActivity activity = getActivity();
if (null == activity) {
return;
}
final ActionBar actionBar = activity.getActionBar();
if (null == actionBar) {
return;
}
actionBar.setSubtitle(subTitle);
}
private final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
FragmentActivity activity = getActivity();
switch (msg.what) {
case Constants.MESSAGE_STATE_CHANGE:
switch (msg.arg1) {
case BluetoothConnection.STATE_CONNECTED:
String name = getString(R.string.title_connected_to, deviceName);
setStatus(name);
break;
case BluetoothConnection.STATE_CONNECTING:
setStatus("Connecting...");
break;
case BluetoothConnection.STATE_NONE:
setStatus("Not connected");
break;
case BluetoothConnection.STATE_LISTEN:
}
break;
case Constants.MESSAGE_DEVICE_NAME:
deviceName = msg.getData().getString(Constants.DEVICE_NAME);
if (activity != null) {
Toast.makeText(activity, "Connected to " + deviceName, Toast.LENGTH_SHORT).show();
}
break;
case Constants.MESSAGE_TOAST:
if (null != activity) {
Toast.makeText(activity, msg.getData().getString(Constants.TOAST), Toast.LENGTH_SHORT).show();
}
break;
case Constants.MESSAGE_READ:
byte[] readBuffer = (byte[]) msg.obj;
//Bitmap bmp = BitmapFactory.decodeByteArray(readBuffer, 0, msg.arg1);
//im.setImageBitmap(bmp);
String path = activity.getFilesDir() + "/mano.xml";
writeBytesToOutputStream(readBuffer, path);
break;
}
}
};
private void sendCommand(int command) {
if (connection.getState() != BluetoothConnection.STATE_CONNECTED) {
Toast.makeText(getActivity(), "You are not connected!", Toast.LENGTH_LONG).show();
return;
}
byte[] bytes = ByteBuffer.allocate(4).putInt(command).array();
connection.write(bytes);
}
private void writeBytesToOutputStream(byte[] bytes, String path) {
File file = new File(path);
OutputStream out;
try {
if(file.exists()){
file.delete();
}
file.createNewFile();
out = new FileOutputStream(file);
out.write(bytes);
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
xml.setFile(file);
}
public class XmlParser extends AsyncTask<Void, Void, String> {
private XmlPullParserFactory xmlFactoryObject;
private XmlPullParser myParser;
private File file;
String value;
public XmlParser() {
try {
xmlFactoryObject = XmlPullParserFactory.newInstance();
myParser = xmlFactoryObject.newPullParser();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
}
public void setFile(File file1) {
file = file1;
execute();
}
@Override
protected void onPreExecute() {
super.onPreExecute();
FileInputStream fis = null;
try {
if(file == null){ // failas == null
Toast.makeText(getActivity(), "NULL", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getActivity(), "NOT NULL " + file.getName(), Toast.LENGTH_LONG).show();
fis = new FileInputStream(file);
myParser.setInput(fis, null);
fis.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
}
@Override
protected String doInBackground(Void... params) {
int event;
try {
event = myParser.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {
String name = myParser.getName();
switch (event) {
case XmlPullParser.START_TAG:
break;
case XmlPullParser.END_TAG:
if (name.equals("from")) {
value = myParser.getAttributeValue(null, "value");
System.out.println("JUST FOR TEST " + value);
event = XmlPullParser.END_DOCUMENT;
}
break;
default:
break;
}
try {
event = myParser.next();
} catch (IOException e) {
e.printStackTrace();
}
}
}catch (XmlPullParserException e) {
e.printStackTrace();
}
return value;
}
@Override
protected void onPostExecute(String aVoid) {
super.onPostExecute(aVoid);
System.out.println("myEND " + aVoid);
Toast.makeText(getActivity(), "THE END!!! " + aVoid, Toast.LENGTH_LONG).show();
}
}
}
编辑
我的文档
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
只是猜测,但这可能是你的问题
try {
event = myParser.next();
} catch (IOException e) {
e.printStackTrace();
}
这是因为如果由于某种原因您的解析器无法移动到下一个元素 - 也许您的 xml 格式不正确? - 然后这个错误永远不会升级,从而让你陷入无限循环。
您可以改为调用 "break"。如果抛出异常。此外,使用 Log class 进行日志记录,如下所示:
try {
event = myParser.next();
} catch (IOException e) {
Log.d(TAG, e.getLocalizedMessage();
break;
}
试试这个:
while (myParser.getEventType() != XmlPullParser.END_DOCUMENT) {
//code
}
我想我找到了解决办法。我需要在 onPostExecute
而不是 onPreExecute
方法上关闭 FileInputStream
。
我是 Android 开发的新手,我构建了一个简单的应用程序,可以通过蓝牙从我的计算机接收 xml
文件。现在我想解析那个 xml
文件,我想用 AsyncTask
doInBackground
方法来做。所以首先在这里我 将字节写入 xml 文件
private void writeBytesToOutputStream(byte[] bytes, String path) {
File file = new File(path);
OutputStream out;
try {
if(file.exists()){
file.delete();
}
file.createNewFile();
out = new FileOutputStream(file);
out.write(bytes);
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// method that sets file and later calls execute().
xml.setFile(file);
}
这是我的内部 AsyncTask class。
public class XmlParser extends AsyncTask<Void, Void, String> {
private XmlPullParserFactory xmlFactoryObject;
private XmlPullParser myParser;
private File file;
String value;
public XmlParser() {
try {
xmlFactoryObject = XmlPullParserFactory.newInstance();
myParser = xmlFactoryObject.newPullParser();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
}
public void setFile(File file1) {
file = file1;
execute();
}
@Override
protected void onPreExecute() {
super.onPreExecute();
FileInputStream fis = null;
try {
if(file == null){
Toast.makeText(getActivity(), "NULL", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getActivity(), "NOT NULL " + file.getName(), Toast.LENGTH_LONG).show();
fis = new FileInputStream(file);
myParser.setInput(fis, null);
fis.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
}
@Override
protected String doInBackground(Void... params) {
int event;
try {
event = myParser.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {
String name = myParser.getName();
switch (event) {
case XmlPullParser.START_TAG:
break;
case XmlPullParser.END_TAG:
if (name.equals("from")) {
value = myParser.getAttributeValue(null, "value");
System.out.println("JUST FOR TEST " + value);
event = XmlPullParser.END_DOCUMENT;
}
break;
default:
break;
}
try {
event = myParser.next();
} catch (IOException e) {
e.printStackTrace();
}
}
}catch (XmlPullParserException e) {
e.printStackTrace();
}
return value;
}
@Override
protected void onPostExecute(String aVoid) {
super.onPostExecute(aVoid);
System.out.println("myEND " + aVoid);
Toast.makeText(getActivity(), "THE END!!! " + aVoid, Toast.LENGTH_LONG).show();
}
}
不知何故方法doInBackground()
永远不会完成。我花了将近四个小时试图修复它,但我找不到问题所在。我还添加了我的完整代码
public class UiFragment extends Fragment {
private static final int REQUEST_CONNECT_DEVICE_SECURE = 1;
private static final int REQUEST_ENABLE_BT = 3;
private String deviceName = null;
private BluetoothAdapter adapter = null;
//private ListView listViewConversation;
//private ArrayAdapter<String> conversationAdapter;
private Button onButton, offButton;
private BluetoothConnection connection = null;
ImageView im;
private XmlParser xml;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_ui, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
//listViewConversation = (ListView) view.findViewById(R.id.in);
onButton = (Button) view.findViewById(R.id.onButton);
offButton = (Button) view.findViewById(R.id.offButton);
im = (ImageView) view.findViewById(R.id.imageView);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
adapter = BluetoothAdapter.getDefaultAdapter();
xml = new XmlParser();
// If the adapter is null, then Bluetooth is not supported
if (adapter == null) {
FragmentActivity activity = getActivity();
Toast.makeText(activity, "Bluetooth is not available", Toast.LENGTH_LONG).show();
activity.finish();
}
}
@Override
public void onStart() {
super.onStart();
// If BT is not on, request that it be enabled.
// setupChat() will then be called during onActivityResult
if (!adapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
// Otherwise, setup the chat session
} else if (connection == null) {
setupChat();
}
}
private void setupChat() {
//conversationAdapter = new ArrayAdapter<String>(getActivity(), R.layout.message);
//listViewConversation.setAdapter(conversationAdapter);
onButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
sendCommand(1);
}
});
offButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
sendCommand(0);
}
});
// Initialize the BluetoothChatService to perform bluetooth connections
connection = new BluetoothConnection(handler);
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CONNECT_DEVICE_SECURE:
// When DeviceListActivity returns with a device to connect
if (resultCode == Activity.RESULT_OK) {
connectDevice(data);
}
break;
case REQUEST_ENABLE_BT:
// When the request to enable Bluetooth returns
if (resultCode == Activity.RESULT_OK) {
// Bluetooth is now enabled, so set up a chat session
setupChat();
} else {
// User did not enable Bluetooth or an error occurred
Toast.makeText(getActivity(), "Bluetooth not enable", Toast.LENGTH_SHORT).show();
getActivity().finish();
}
}
}
private void connectDevice(Intent data) {
// Get the device MAC address
String address = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
// Get the BluetoothDevice object
BluetoothDevice device = adapter.getRemoteDevice(address);
// Attempt to connect to the device
connection.connect(device);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.secure_connect_scan: {
// Launch the DeviceListActivity to see devices and do scan
Intent serverIntent = new Intent(getActivity(), DeviceListActivity.class);
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_SECURE);
return true;
}
}
return false;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_device_list, menu);
}
private void setStatus(CharSequence subTitle) {
FragmentActivity activity = getActivity();
if (null == activity) {
return;
}
final ActionBar actionBar = activity.getActionBar();
if (null == actionBar) {
return;
}
actionBar.setSubtitle(subTitle);
}
private final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
FragmentActivity activity = getActivity();
switch (msg.what) {
case Constants.MESSAGE_STATE_CHANGE:
switch (msg.arg1) {
case BluetoothConnection.STATE_CONNECTED:
String name = getString(R.string.title_connected_to, deviceName);
setStatus(name);
break;
case BluetoothConnection.STATE_CONNECTING:
setStatus("Connecting...");
break;
case BluetoothConnection.STATE_NONE:
setStatus("Not connected");
break;
case BluetoothConnection.STATE_LISTEN:
}
break;
case Constants.MESSAGE_DEVICE_NAME:
deviceName = msg.getData().getString(Constants.DEVICE_NAME);
if (activity != null) {
Toast.makeText(activity, "Connected to " + deviceName, Toast.LENGTH_SHORT).show();
}
break;
case Constants.MESSAGE_TOAST:
if (null != activity) {
Toast.makeText(activity, msg.getData().getString(Constants.TOAST), Toast.LENGTH_SHORT).show();
}
break;
case Constants.MESSAGE_READ:
byte[] readBuffer = (byte[]) msg.obj;
//Bitmap bmp = BitmapFactory.decodeByteArray(readBuffer, 0, msg.arg1);
//im.setImageBitmap(bmp);
String path = activity.getFilesDir() + "/mano.xml";
writeBytesToOutputStream(readBuffer, path);
break;
}
}
};
private void sendCommand(int command) {
if (connection.getState() != BluetoothConnection.STATE_CONNECTED) {
Toast.makeText(getActivity(), "You are not connected!", Toast.LENGTH_LONG).show();
return;
}
byte[] bytes = ByteBuffer.allocate(4).putInt(command).array();
connection.write(bytes);
}
private void writeBytesToOutputStream(byte[] bytes, String path) {
File file = new File(path);
OutputStream out;
try {
if(file.exists()){
file.delete();
}
file.createNewFile();
out = new FileOutputStream(file);
out.write(bytes);
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
xml.setFile(file);
}
public class XmlParser extends AsyncTask<Void, Void, String> {
private XmlPullParserFactory xmlFactoryObject;
private XmlPullParser myParser;
private File file;
String value;
public XmlParser() {
try {
xmlFactoryObject = XmlPullParserFactory.newInstance();
myParser = xmlFactoryObject.newPullParser();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
}
public void setFile(File file1) {
file = file1;
execute();
}
@Override
protected void onPreExecute() {
super.onPreExecute();
FileInputStream fis = null;
try {
if(file == null){ // failas == null
Toast.makeText(getActivity(), "NULL", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getActivity(), "NOT NULL " + file.getName(), Toast.LENGTH_LONG).show();
fis = new FileInputStream(file);
myParser.setInput(fis, null);
fis.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
}
@Override
protected String doInBackground(Void... params) {
int event;
try {
event = myParser.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {
String name = myParser.getName();
switch (event) {
case XmlPullParser.START_TAG:
break;
case XmlPullParser.END_TAG:
if (name.equals("from")) {
value = myParser.getAttributeValue(null, "value");
System.out.println("JUST FOR TEST " + value);
event = XmlPullParser.END_DOCUMENT;
}
break;
default:
break;
}
try {
event = myParser.next();
} catch (IOException e) {
e.printStackTrace();
}
}
}catch (XmlPullParserException e) {
e.printStackTrace();
}
return value;
}
@Override
protected void onPostExecute(String aVoid) {
super.onPostExecute(aVoid);
System.out.println("myEND " + aVoid);
Toast.makeText(getActivity(), "THE END!!! " + aVoid, Toast.LENGTH_LONG).show();
}
}
}
编辑
我的文档
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
只是猜测,但这可能是你的问题
try {
event = myParser.next();
} catch (IOException e) {
e.printStackTrace();
}
这是因为如果由于某种原因您的解析器无法移动到下一个元素 - 也许您的 xml 格式不正确? - 然后这个错误永远不会升级,从而让你陷入无限循环。
您可以改为调用 "break"。如果抛出异常。此外,使用 Log class 进行日志记录,如下所示:
try {
event = myParser.next();
} catch (IOException e) {
Log.d(TAG, e.getLocalizedMessage();
break;
}
试试这个:
while (myParser.getEventType() != XmlPullParser.END_DOCUMENT) {
//code
}
我想我找到了解决办法。我需要在 onPostExecute
而不是 onPreExecute
方法上关闭 FileInputStream
。