我正在尝试从android活动(一个简单的登录表单)做一个http请求/响应但是在我完成代码后它给了我一个错误,因为我必须把它放在一个线程中,我不熟悉async任务,但我已经尝试实现它,但是,现在当我运行程序并点击提交它logcat给了我类似的东西
FATAL EXCEPTION: AsyncTask #1
Process: com.example.httpgetandroidexample, PID: 1131
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:300)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6094)
at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:824)
at android.view.View.requestLayout(View.java:16431)
at android.view.View.requestLayout(View.java:16431)
at android.view.View.requestLayout(View.java:16431)
at android.view.View.requestLayout(View.java:16431)
at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:352)
at android.view.View.requestLayout(View.java:16431)
at android.widget.TextView.checkForRelayout(TextView.java:6600)
at android.widget.TextView.setText(TextView.java:3813)
at android.widget.TextView.setText(TextView.java:3671)
at android.widget.TextView.setText(TextView.java:3646)
at com.example.httpgetandroidexample.MainActivity$AsyncTaskRunner.doInBackground(MainActivity.java:87)
at com.example.httpgetandroidexample.MainActivity$AsyncTaskRunner.doInBackground(MainActivity.java:1)
at android.os.AsyncTask$2.call(AsyncTask.java:288)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
... 4 more
我不明白为什么!这是我的Android活动:
package com.example.httpgetandroidexample;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
public TextView content;
EditText name,pass;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
name = (EditText)findViewById(R.id.name);
pass = (EditText)findViewById(R.id.pass);
content = (TextView)findViewById(R.id.text);
Button button=(Button)findViewById(R.id.but);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AsyncTaskRunner runner = new AsyncTaskRunner();
runner.execute();
}
});
}
class AsyncTaskRunner extends AsyncTask<String, String, String> {
private String resp;
@Override
protected String doInBackground(String... params) {
publishProgress("Working..."); // Calls onProgressUpdate()
try{
// URLEncode user defined data
String nameValue = URLEncoder.encode(name.getText().toString(), "UTF-8");
String passValue = URLEncoder.encode(pass.getText().toString(), "UTF-8");
// Create http cliient object to send request to server
HttpClient Client = new DefaultHttpClient();
// Create URL string
String URL = "http://localhost:8080/login/web?user="+nameValue+"&pass="+passValue;
//Log.i("httpget", URL);
try
{
String SetServerString = "";
// Create Request to server and get response
HttpGet httpget = new HttpGet(URL);
ResponseHandler<String> responseHandler = new BasicResponseHandler();
SetServerString = Client.execute(httpget, responseHandler);
// Show response on activity
content.setText(SetServerString);
}
catch(Exception ex)
{
content.setText("fail");
System.out.println(ex);
resp="fail";
}
}
catch(UnsupportedEncodingException ex)
{
content.setText("FailAndroid!");
resp="fail";
}
return resp;
}
@Override
protected void onPostExecute(String result) {
content.setText(result);
}
protected void onPreExecute() {
}
@Override
protected void onProgressUpdate(String... text) {
content.setText(text[0]);
}
}
}
我的代码显示没有错误,甚至没有警告,但是当我按下提交按钮时,它会在“工作”消息出现后强行关闭,有人知道为什么? 提前谢谢
在你的帮助下(谢谢大家!)我修改了我的活动代码:
package com.example.httpgetandroidexample;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
public TextView content;
EditText name,pass;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
name = (EditText)findViewById(R.id.name);
pass = (EditText)findViewById(R.id.pass);
content = (TextView)findViewById(R.id.text);
Button button=(Button)findViewById(R.id.but);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AsyncTaskRunner runner = new AsyncTaskRunner();
runner.execute();
}
});
}
class AsyncTaskRunner extends AsyncTask<String, String, String> {
private String resp;
@Override
protected String doInBackground(String... params) {
publishProgress("Working..."); // Calls onProgressUpdate()
try{
// URLEncode user defined data
String nameValue = URLEncoder.encode(name.getText().toString(), "UTF-8");
String passValue = URLEncoder.encode(pass.getText().toString(), "UTF-8");
// Create http cliient object to send request to server
HttpClient Client = new DefaultHttpClient();
// Create URL string
String URL = "http://localhost:8080/login/web?user="+nameValue+"&pass="+passValue;
//Log.i("httpget", URL);
try
{
String SetServerString = "";
// Create Request to server and get response
HttpGet httpget = new HttpGet(URL);
ResponseHandler<String> responseHandler = new BasicResponseHandler();
SetServerString = Client.execute(httpget, responseHandler);
// Show response on activity
return SetServerString;
}
catch(Exception ex)
{
Log.i("MyActivity","Exception");
}
}
catch(UnsupportedEncodingException ex)
{
Log.i("MyActivity","UnsupportedEncodingException");
}
return resp;
}
@Override
protected void onPostExecute(String result) {
content.setText(result);
}
protected void onPreExecute() {
}
@Override
protected void onProgressUpdate(String... text) {
content.setText(text[0]);
}
}
}
但现在我收到了Log.i("MyActivity","Exception");
消息,我仍然做错了什么?
更新
对于我的最后一次尝试,我再次按照一些在线教程修改了代码,这就是我所做的
package com.example.httpgetandroidexample;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
public TextView content;
EditText name,pass;
String URL;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
name = (EditText)findViewById(R.id.name);
pass = (EditText)findViewById(R.id.pass);
content = (TextView)findViewById(R.id.text);
Button button=(Button)findViewById(R.id.but);
try {
String nameValue = URLEncoder.encode(name.getText().toString(), "UTF-8");
String passValue = URLEncoder.encode(pass.getText().toString(), "UTF-8");
URL = "http://localhost:8080/login/web?user="+nameValue+"&pass="+passValue;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AsyncTaskRunner runner = new AsyncTaskRunner();
runner.execute(new String[ ] { URL });
}
});
}
private class AsyncTaskRunner extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return response;
}
@Override
protected void onPostExecute(String result) {
content.setText(result);
}
}
}
这里的logcat是详细模式:
Permission denied (missing INTERNET permission?)
at java.net.InetAddress.lookupHostByName(InetAddress.java:418)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)
at java.net.InetAddress.getAllByName(InetAddress.java:214)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:137)
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
at com.example.httpgetandroidexample.MainActivity$AsyncTaskRunner.doInBackground(MainActivity.java:69)
at com.example.httpgetandroidexample.MainActivity$AsyncTaskRunner.doInBackground(MainActivity.java:1)
at android.os.AsyncTask$2.call(AsyncTask.java:288)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
Caused by: libcore.io.GaiException: getaddrinfo failed: EAI_NODATA (No address associated with hostname)
at libcore.io.Posix.getaddrinfo(Native Method)
at libcore.io.ForwardingOs.getaddrinfo(ForwardingOs.java:61)
at java.net.InetAddress.lookupHostByName(InetAddress.java:405)
... 17 more
Caused by: libcore.io.ErrnoException: getaddrinfo failed: EACCES (Permission denied)
... 20 more
从我理解的是它缺少许可,但问题是我在我的清单文件中有它:
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" android:permission="android.permission.INTERNET">
答案 0 :(得分:5)
Logcat错误:
引起:android.view.ViewRootImpl $ CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触及其视图。
您尝试使用doInBackground
中的UI线程,
content.setText("fail");
你无法通过后台线程使用onPostExecute
触摸ui线程中的任何内容来处理UI
这是你想要的一个样本。
private class DownloadWebPageTask extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return response;
}
@Override
protected void onPostExecute(String result) {
textView.setText(result);
}
}
您需要从doInBackground
样本中:return response;
表示您需要更改:
样本:
1- AsyncTask<String, Void, String>
&lt; ---最后一个值是doInBackground
protected String doInBackground
更多信息的内容
2- return response;
&lt; ---将返回类型更改为String
3 - 返回您的值protected void onPostExecute(String result)
4- onPostExecute
&lt; ---这也必须是String
然后使用onPostExecute(String result)
6.5. Example: AsyncTask
中的&lt; ---结果是您的字符串
来自This site String nameValue = URLEncoder.encode(name.getText().toString(), "UTF-8");
String passValue = URLEncoder.encode(pass.getText().toString(), "UTF-8");
<强>更新强>
您再次使用UI:
doInBackground
如果您想要这个值,您可以将它们发送到asynctask的构造函数或作为参数发送到catch(UnsupportedEncodingException ex)
{
ex.printStackTrace();
}
,我推荐第二种方式
作为您在try catch语句中的代码,您的应用程序未关闭,因为您不打印任何对catch有用的东西,如果您使用catch它更合适打印错误太像:
android:permission="android.permission.INTERNET">
更新2
您在代码中声明您的Android权限如下:
<manifest xlmns:android...>
...
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
</manifest>
但您必须添加以下权限:
<?xml version="1.0" encoding="utf-8"?>
<manifest
......
......
.....>
<uses-sdk
...... />
<uses-permission android:name="android.permission.INTERNET" />
<application
.......
.......
</application>
</manifest>
你的清单必须像:
{{1}}
答案 1 :(得分:1)
引起:android.view.ViewRootImpl $ CalledFromWrongThreadException: 只有创建视图层次结构的原始线程才能触及它 视图。
stacktrace说你正在从一个错误的背景线程中更新ui。
你有
content.setText(SetServerString);
您正在更新doInbackground
中的错误。
您只能从ui线程更新ui。在后台线程上调用doInBackground
。在ui线程上调用onPostExecute
。因此,您可以doInBackgorund
返回并在onPostExecute
更新ui。
检查主题 4个步骤 @
http://developer.android.com/reference/android/os/AsyncTask.html
而不是System.out.println(ex);
使用Log
来记录信息。
http://developer.android.com/reference/android/util/Log.html
答案 2 :(得分:1)
您无法在doInBackground中使用UI!每当您的代码进入 doInBackground 中的content.setText()
时,它都会崩溃。
答案 3 :(得分:1)
content.setText();
中的{p> doInbackground
正在犯错误。您无法更新doInbackground
中的用户界面。任何更改用户界面的内容都应移至onPostExecute
答案 4 :(得分:1)
用户界面上的所有修改(用户看到的任何内容,如Buttons或TextFields)必须由主线程(UI线程)执行。 doInBackground()方法中的代码在不同的线程上运行。因此,您应该在此处下载数据(这是耗时的计算),然后使用onPostExecute()方法中的查询信息更改UI。