Android DownloadFilesTask concept
При попытке с клиентским сервером (получение данных MySQL) с помощью учебника я получаю много ошибок. Я просто прочитал некоторые темы здесь, и я понял, что самая большая ошибка, которую я получаю
Ошибка в http connectionandroid.os.NetworkOnMainThreadException E/log_tag: Ошибка преобразования результата java.lang.NullPointerException
может быть потому, что мне нужна вспомогательная задача между потоком и обработчиком.
У меня есть следующий код, я понимаю эту концепцию и обычно она должна работать.
package de.irgendwas;
import android.app.Activity;
import android.net.ParseException;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.appindexing.Action;
import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.appindexing.Thing;
import com.google.android.gms.common.api.GoogleApiClient;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
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 java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
public class MainActivity extends Activity {
private GoogleApiClient client;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/** Called when the activity is first created. */
String result = null;
InputStream is = null;
StringBuilder sb = null;
//http post
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://localhost/connect_db.php");
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
Log.e("log_tag", "connection established");
} catch (Exception e) {
Log.e("log_tag", "Error in http connection" + e.toString());
}
//convert response to string
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8"), 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());
}
//paring data
int fd_id = 0;
String fd_name = "";
try {
JSONArray jArray = new JSONArray(result);
JSONObject json_data = null;
Toast.makeText(getBaseContext(), "1. try Block", Toast.LENGTH_LONG).show();
for (int i = 0; i < jArray.length(); i++) {
json_data = jArray.getJSONObject(i);
fd_id = json_data.getInt("artist");
fd_name = json_data.getString("title");
}
} catch (JSONException e1) {
Toast.makeText(getBaseContext(), "No Data Found", Toast.LENGTH_LONG).show();
} catch (ParseException e1) {
e1.printStackTrace();
}
//print received data
TextView t = (TextView) findViewById(R.id.text);
t.setText("ID: " + fd_id + " Name: " + fd_name);
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
}
/**
* ATTENTION: This was auto-generated to implement the App Indexing API.
* See https://g.co/AppIndexing/AndroidStudio for more information.
*/
public Action getIndexApiAction() {
Thing object = new Thing.Builder()
.setName("Main Page") // TODO: Define a title for the content shown.
// TODO: Make sure this auto-generated URL is correct.
.setUrl(Uri.parse("http://[ENTER-YOUR-URL-HERE]"))
.build();
return new Action.Builder(Action.TYPE_VIEW)
.setObject(object)
.setActionStatus(Action.STATUS_TYPE_COMPLETED)
.build();
}
@Override
public void onStart() {
super.onStart();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client.connect();
AppIndex.AppIndexApi.start(client, getIndexApiAction());
}
@Override
public void onStop() {
super.onStop();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
AppIndex.AppIndexApi.end(client, getIndexApiAction());
client.disconnect();
}
}
Я не буду публиковать php-скрипт на сервере, потому что если я вызываю URL через браузер, он доставляет мои тестовые данные правильно, так что все должно быть в порядке.
Теперь при выполнении приложения я получаю ошибки выше. При поиске в Интернете я нашел концепцию DownloadFilesTask, похоже, это должно быть решением. Но я не получу это, я не могу реализовать это в своем коде. Может кто-нибудь помочь или есть хороший учебник где-то кроме того, на developer.android.
2 ответа
Ошибка возникает из-за того, что вы хотите выполнить сетевой процесс в потоке пользовательского интерфейса. Вы должны убрать его из своей темы пользовательского интерфейса. Для вашего случая вы можете использовать AsyncTask.
AsyncTask - это механизм для выполнения операций в фоновом потоке без необходимости вручную обрабатывать создание или выполнение потока. AsyncTasks были разработаны для использования в коротких операциях (максимум несколько секунд), и вы можете использовать Service и / или Executor для очень долго выполняющихся задач.
AsyncTask обычно используется для длительных задач, которые невозможно выполнить в потоке пользовательского интерфейса, таких как загрузка сетевых данных из API или индексация данных из других мест на устройстве.
Пожалуйста, прочтите Создание и выполнение асинхронных задач.
Вот пример использования AsyncTask в процессе, связанном с сетью:
public class MainActivity extends Activity {
private ImageView ivBasicImage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ivBasicImage = (ImageView) findViewById(R.id.ivBasicImage);
String url = "https://i.imgur.com/tGbaZCY.jpg";
// Download image from URL and display within ImageView
new ImageDownloadTask(ivBasicImage).execute(url);
}
// Defines the background task to download and then load the image within the ImageView
private class ImageDownloadTask extends AsyncTask<String, Void, Bitmap> {
ImageView imageView;
public ImageDownloadTask(ImageView imageView) {
this.imageView = imageView;
}
protected Bitmap doInBackground(String... addresses) {
Bitmap bitmap = null;
InputStream in;
try {
// 1. Declare a URL Connection
URL url = new URL(addresses[0]);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// 2. Open InputStream to connection
conn.connect();
in = conn.getInputStream();
// 3. Download and decode the bitmap using BitmapFactory
bitmap = BitmapFactory.decodeStream(in);
} catch (IOException e) {
e.printStackTrace();
} finally {
if(in != null)
in.close();
}
return bitmap;
}
// Fires after the task is completed, displaying the bitmap into the ImageView
@Override
protected void onPostExecute(Bitmap result) {
// Set bitmap image for the result
imageView.setImageBitmap(result);
}
}
}
Вы должны также зарегистрировать это исключение Log.e("log_tag", "Error in http connection" + e.toString());
Это из-за этой линии
HttpPost httppost = new HttpPost("http://localhost/connect_db.php");
Это всегда будет указывать на локальный хост устройства, а не на сервер. Так что вы должны использовать:
HttpPost httppost = new HttpPost("http://10.0.2.2/connect_db.php");
Это является причиной исключения nullpointer на result