Android - zapytanie MySQL JSON daje NetworkOnMainThreadException
Próbuję uruchomić to działanie, aby zapytać bazę danych o zapełnienie tabeli. Próbowałem podążać za fragmentem, który znalazłem w Internecie, jedyny problem polega na tym, że niezależnie od tego otrzymuję błąd „connectionandroid.os.NetworkOnMainThreadException”.
Próbowałem umieścić program obsługi, jak sugerowano na wielu forach, używając AsyncTask i zrobić to w tle, ale nadal nic. Wiem, że błąd pojawia się, gdy długie zapytanie jest wysyłane do bazy danych, ale to zapytanie trwa prawdopodobnie 0,1 s. Mam lokalną bazę danych, chociaż uzyskuję do niej dostęp za pomocą publicznego adresu IP, a db jest bardzo mała.
Oto mój kod PHP:
<code><?php $hostname_localhost ="localhost"; $database_localhost ="DB"; $username_localhost ="root"; $password_localhost ="pwd"; mysql_connect($hostname_localhost,$username_localhost,$password_localhost); mysql_select_db($database_localhost); $sql=mysql_query("select * from friendlist where Id1 = 1"); while($row=mysql_fetch_assoc($sql)) $output[]=$row; print(json_encode($output)); mysql_close(); ?> </code>
Kod działa, gdybym przejrzał na stronę, zobaczyłem wyniki (mam tylko 3 wiersze na chwilę).
Oto część java:
<code>import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.app.ListActivity; import android.net.ParseException; import android.os.Bundle; import android.util.Log; import android.widget.Toast; public class MySQLAndroidActivity extends ListActivity { JSONArray jArray; String result = null; InputStream is = null; StringBuilder sb=null; HttpResponse response; HttpEntity entity; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(); //http post try{ HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost("http://X.X.X.X/test.php"); httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); response = httpclient.execute(httppost); entity = response.getEntity(); is = entity.getContent(); }catch(Exception e){ Log.e("log_tag", "Error in http connection"+e.toString()); System.exit(1); } //convert response to string try{ BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8); sb = new StringBuilder(); sb.append(reader.readLine() + "\n"); String line="0"; while ((line = reader.readLine()) != null) { sb.append(line + "\n"); } is.close(); result=sb.toString(); }catch(Exception e){ Log.e("log_tag", "Error converting result "+e.toString()); } //parsing data String idfriend; String id1; String id2; try{ jArray = new JSONArray(result); JSONObject json_data=null; for(int i=0;i<jArray.length();i++){ json_data = jArray.getJSONObject(i); idfriend=json_data.getString("Idfriend"); id1=json_data.getString("Id1"); id2=json_data.getString("Id2"); System.out.println("id1: " + id1); } } catch(JSONException e1){ Toast.makeText(getBaseContext(), "No Id found" ,Toast.LENGTH_LONG).show(); } catch (ParseException e1) { e1.printStackTrace(); } } } </code>
Próbowałem również użyć prostego działania, a nie ListActivity.
Mam prawie podobny kod, ale ten używa innej metody. W rzeczywistości nie uzyskuje wyniku, na php, po prostu zwraca znaki, czy istnieje 0 lub więcej pobranych wierszy. W tym przypadku potrzebuję czegoś na wyższym poziomie, ponieważ będę musiał uzyskać wartości niektórych określonych pól.
EDYTOWAĆ:
Zgodnie z żądaniem, stacktrace:
<code> Error in http connectionandroid.os.NetworkOnMainThreadException 04-17 06:44:17.921: W/System.err(24207): java.lang.Exception 04-17 06:44:17.921: W/System.err(24207): at com.mysql.android.MySQLAndroidActivity.onCreate(MySQLAndroidActivity.java:56) 04-17 06:44:17.921: W/System.err(24207): at android.app.Activity.performCreate(Activity.java:4465) 04-17 06:44:17.921: W/System.err(24207): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049) 04-17 06:44:17.921: W/System.err(24207): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920) 04-17 06:44:17.921: W/System.err(24207): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981) 04-17 06:44:17.921: W/System.err(24207): at android.app.ActivityThread.access$600(ActivityThread.java:123) 04-17 06:44:17.921: W/System.err(24207): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147) 04-17 06:44:17.921: W/System.err(24207): at android.os.Handler.dispatchMessage(Handler.java:99) 04-17 06:44:17.921: W/System.err(24207): at android.os.Looper.loop(Looper.java:137) 04-17 06:44:17.931: W/System.err(24207): at android.app.ActivityThread.main(ActivityThread.java:4424) 04-17 06:44:17.931: W/System.err(24207): at java.lang.reflect.Method.invokeNative(Native Method) 04-17 06:44:17.931: W/System.err(24207): at java.lang.reflect.Method.invoke(Method.java:511) 04-17 06:44:17.931: W/System.err(24207): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 04-17 06:44:17.931: W/System.err(24207): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 04-17 06:44:17.931: W/System.err(24207): at dalvik.system.NativeStart.main(Native Method) </code>
EDIT2:
Oto coś bardzo podobnego do wersji, którą zrobiłem z AsyncTask (tworzę ją w locie, bez kompilatora, więc może nie być idealna; ale jest bardzo podobna do tej, którą robiłem wcześniej):
<code> @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); new LoadTask().execute(); } private class LoadTask extends AsyncTask<Void, Integer, Void> { @Override protected void onPreExecute() { } @Override protected Void doInBackground(Void... params) { synchronized (this) { Looper.prepare(); doStuff() //this method basically contains what it is inside the onCreate. } return null; } } } </code>
- Pamiętam, że musiałem użyć „Looper.prepare ();”. Dodałem to przed 'doStuff ();'
EDYCJA 2:
<code>import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.app.ListActivity; import android.net.ParseException; import android.os.AsyncTask; import android.os.Bundle; import android.os.Looper; import android.util.Log; import android.widget.Toast; public class MySQLAndroidActivity extends ListActivity { JSONArray jArray; String result = null; InputStream is = null; StringBuilder sb = null; HttpResponse response; HttpEntity entity; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); new LoadTask.execute(); } private class LoadTask extends AsyncTask < Void, Integer, Void > {@Override protected void onPreExecute() { } @Override protected Void doInBackground(Void...params) { Looper.prepare(); doStuff(); return null; } } public void doStuff() { ArrayList < NameValuePair > nameValuePairs = new ArrayList < NameValuePair > (); //http post try { HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost("http://X.X.X.X/test.php"); httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); response = httpclient.execute(httppost); entity = response.getEntity(); is = entity.getContent(); } catch (Exception e) { Log.e("log_tag", "Error in http connection" + e.toString()); System.exit(1); } //convert response to string try { BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8); sb = new StringBuilder(); sb.append(reader.readLine() + "\n"); String line = "0"; while ((line = reader.readLine()) != null) { sb.append(line + "\n"); } is.close(); result = sb.toString(); } catch (Exception e) { Log.e("log_tag", "Error converting result " + e.toString()); } //parsing data String idfriend; String id1; String id2; try { jArray = new JSONArray(result); JSONObject json_data = null; System.out.println("Length " + jArray.length()); Log.d("DB", "Length " + jArray.length()); for (int i = 0; i < jArray.length(); i++) { System.out.println("counter " + i); json_data = jArray.getJSONObject(i); idfriend = json_data.getString("Idfriend"); id1 = json_data.getString("Id1"); id2 = json_data.getString("Id2"); System.out.println("id1: " + id1); } } catch (JSONException e1) { Log.d("DB", "Error somewhere"); } catch (ParseException e1) { e1.printStackTrace(); } } } </code>
Z góry dziękuję,
N.