AsyncTaskやタイマーを使用してXMLを取得する方法は?
-
19-09-2019 - |
質問
を繰り返し、サーバーからXMLデータを取得するためには、私は<のhref = "http://www.mail-archive.com/android-beginners@googlegroups.com/あたりとしてAsyncTaskやタイマーを使用しようとしていますmsg11150.html」のrel = "nofollowをnoreferrer">マーク・マーフィーの提案するます。
私は次のエラーを取得する:
01-07 16:11:26.705: ERROR/AndroidRuntime(729):
Caused by: java.lang.RuntimeException:
Can't create handler inside thread that has not
called Looper.prepare()
私はWindows上のEclipseとSDK 1.5を使用しています。
私はStackOverflowの上とAndroid Developersグループに、ドキュメントで見てきたが、私はエラーを引き起こすか、またはどのようにそれを修正する何クリアしていないよ。
私は一度データを取得することができます - すなわち、非同期およびタイマーなし - 。問題なくSAXを経由してそれを解析
以下の全アプリのコード。
すべての素朴なエラーを言い訳してください:私は、Androidに非常に新しいです。
。package com.foo.bar.myactivity;
import java.net.URL;
import java.util.Timer;
import java.util.TimerTask;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
public class MyActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Timer timer;
timer = new Timer();
timer.schedule(new MyTimerTask(), 0, 1000);
}
public class MyAsyncTask extends AsyncTask<String, Integer, MyData> {
protected MyData doInBackground(String... string) {
MyData myData = new MyData();
try {
URL url = new URL("http://www.example.com/my.xml");
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
MyHandler myHandler = new MyHandler();
xr.setContentHandler(myHandler);
System.setProperty("http.proxyHost", "www-cache.example.com");
System.setProperty("http.proxyPort", "80");
xr.parse(new InputSource(url.openStream()));
myData = myHandler.getParsedData();
return myData;
} catch (Exception e) {
Log.e(">>>>>>>>>>>> Error getting myData: ", e.getMessage(), e);
return myData;
}
}
protected void onProgressUpdate(Integer... progress) {
// setProgressPercent(progress[0]);
}
protected void onPostExecute(MyData myData) {
Log.d(">>>>>>>>>>>>>My data: ", myData.toString());
}
}
public class MyTimerTask extends TimerTask {
public void run() {
try {
new MyAsyncTask().execute("");
} catch (Exception e) {
Log.e(">>>>>>>>>>>> Error executing MyAsyncTask: ", e.getMessage(), e);
}
}
}
}
解決
問題はTimerTaskを使用しています。 TimerTaskを実行ハンドラに投稿する必要があり、このような何かます:
private Handler mHandler = new Handler();
public class MyTimerTask extends TimerTask {
public void run() {
mHandler.post(
new Runnable() {
public void run() {
new MyAsyncTask().execute("");
}
};
)
}
}
もちろんこれは少し醜いなっているので、匿名クラスを取り出すことをお勧めします。
他のヒント
私はこれがジェームズの答えのおかげで動作するようになっています。
私はそれが誰にも便利だ場合には、以下のコードを含めました。
警告の開発者!コードは私のために動作しますが、エラーを含むことがあります。
package com.example.test;
import java.net.URL;
import java.util.Timer;
import java.util.TimerTask;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
public class MyXmlPoller extends Activity {
private Handler handler = new Handler();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new Timer().schedule(new MyTimerTask(), 0, 1000);
}
private class MyAsyncTask extends AsyncTask<Integer, Integer, MyData> {
protected MyData doInBackground(Integer... counter) {
MyData myData = new MyData();
try {
URL url = new URL("http://www.example.com/my.xml");
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
MySAXHandler mySAXHandler = new Handler();
xr.setContentHandler(mySAXHandler);
xr.parse(new InputSource(url.openStream()));
myData = mySAXHandler.getParsedData();
return myData;
} catch (Exception e) {
Log.e("!!!!!!!!!! MyAsyncTask doInBackground error", e.getMessage(), e);
return myData;
}
}
protected void onPostExecute(MyData myData) {
Log.d("+++++++++++++ MyAsyncTask onPostExecute", myData.toString());
}
} // MyAsyncTask
public class MyTimerTask extends TimerTask {
private Runnable runnable = new Runnable() {
public void run() {
new MyAsyncTask().execute();
}
};
public void run() {
handler.post(runnable);
}
}
}
問題は、あなたがLooper.prepare()
呼び出されていないことのようです。あなたはLooper
ののドキュメントを見ている可能性があります。
A Handler
のでメッセージループを必要とメッセージを処理するために、デフォルトでスレッドは1を持っていません。
これは<のhref = "http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob_plain;f=core/java/android/os/AsyncTaskようです。ジャワ; HB = HEAD」のrel = "nofollowをnoreferrer"> AsyncTask
が内部のHandler
を使用していますので、Looper.prepare()
であなたのrun()
方法の上部にMyTimerTask
を追加し、それはあなたの問題を解決する必要があります。
私はアラームマネージャでサービスを使用すると思います。
I Intent updateIntent = new Intent(ACTION_UPDATE_ALL);
updateIntent.setClass(this, UpdateService.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, updateIntent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC, nextUpdate, pendingIntent);
問題は、doInBackground()が中で実行されることをスレッドでHandlerオブジェクトを作成することはできませんです。私はonPreExecute()メソッドを実装し、そこにあなたのセットアップコードを置きます。 onPreExecute()メソッドに次の行を移動してみます:
URL url = new URL("http://www.example.com/my.xml");
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
MyHandler myHandler = new MyHandler();
xr.setContentHandler(myHandler);