I've been having this problem for a whole day now. I've made an app which gets data from my server using JSON and converts it and displays it in the app. I made this as a separate working app with only one activity. The next step is to make an app which uses multiple activities. I've made a home screen with a button with an intent to the activity which is supposed to work the same as the other app. When I open the app everything works fine, but when I intent to the other (Recepten) screen, the app crashes. I guess it is because it's not running on the ui thread but I just can't figure it out.. If somebody could please help me, that would be great! Thanks a lot in advance.
The Error
11-03 18:03:35.460 6159-6235/me.janvandijk.receptenapp E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #1
Process: me.janvandijk.receptenapp, PID: 6159
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:304)
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:818)
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:200)
at android.os.Handler.<init>(Handler.java:114)
at android.app.Activity.<init>(Activity.java:794)
at me.janvandijk.receptenapp.Recepten.<init>(Recepten.java:24)
at me.janvandijk.receptenapp.ReceptenDefine.<init>(ReceptenDefine.java:12)
at me.janvandijk.receptenapp.Recepten$ReceptenAsynTask.doInBackground(Recepten.java:60)
at me.janvandijk.receptenapp.Recepten$ReceptenAsynTask.doInBackground(Recepten.java:42)
at android.os.AsyncTask$2.call(AsyncTask.java:292)
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:818)
The JSON:
[{"id":"1",
"naam":"Bastogneparfait a la Kim",
"beschrijving":"Gemaakt van Bastogne, het lekkerste gerecht ooit!",
"ingredienten":"Bastogne parfait ingredi\u00ebnten\r\n40 gram eierdooiers (gepasteuriseerd)\r\n45 gram hele eieren (gepasteuriseerd)\r\n100 gram suiker \r\n2,5 dl slagroom ongezoet\r\n4 bastognekoeken \r\nKaralmelsaus ingredi\u00ebnten\r\n100 gram suiker \r\n2 dl koksroom ",
"bereiding":"Slagroom opkloppen tot yoghurt dikte. De eidooiers, hele eieren en suiker in een bekken doen en au bain-marie verwarmen tot 37 graden Celsius. Koud kloppen in de keukenmachine tot een luchtige massa. Spatel de massa door de slagroom. Kruimel de bastognekoeken en spatel ze voorzichtig door de massa. Vul de vormpjes en zet in diepvries.\nBereidingswijze karamelsaus\nDoe de suiker in een pan en verwarm de suiker tot deze is gekaramelliseerd. Haal de pan van het vuur en voeg de koksroom toe. Laat de karamel goed oplossen in de koksroom regelmatig roeren. Als de massa glad is af laten koelen.\nOpdienen\nHaal de parfait uit de vorm en leg in een tapasschaaltje. Doe er karamelsaus bij en een toefje slagroom op de parfait. Eventueel af garneren met een takje mint.",
"auteur":"3",
"timestamp":"2015-10-22 14:42:14"},
{"id":"2",
"naam":"Vlindertjes met kip, spekjes en roomsaus",
"beschrijving":"Lekker lekker!",
"ingredienten":"Een beetje liefde\r\nEen beetje kip\r\nEen beetje spekjes\r\nEen beetje kruidenshit\r\nEen beetje creeemeee freeescheee\r\nEn vlindertjes",
"bereiding":"In pan hop klaar!",
"auteur":"1",
"timestamp":"2015-11-02 09:50:54"}]
public class Home extends Activity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
}
public void showReceptenScherm(View view){
Intent intent = new Intent(Home.this, Recepten.class);
startActivity(intent);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_home, menu);
return true;
}
public void onRadioButtonClicked(View view) {
Toast.makeText(getApplicationContext(), "Sending your vote..", Toast.LENGTH_LONG).show();
}
The Recepten Activity
ListView list;
ReceptenAdapter adapter;
ArrayList<ReceptenDefine> receptenList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recepten);
list = (ListView)findViewById(R.id.receptenList);
receptenList = new ArrayList<>();
new ReceptenAsynTask().execute("http://janvandijk.me/zooi/receptenapp/getrecipes.php?type=request&datatype=recepten");
}
public class ReceptenAsynTask extends AsyncTask<String, Void, Boolean> {
@Override
protected Boolean doInBackground(String... params) {
try {
HttpClient client = new SystemDefaultHttpClient();
HttpPost post = new HttpPost(params[0]);
HttpResponse response = client.execute(post);
int status = response.getStatusLine().getStatusCode();
if (status == 200){
HttpEntity entity = response.getEntity();
String data = EntityUtils.toString(entity);
JSONArray jArray = new JSONArray(data); //jArray.length()
for (int i=0; i<jArray.length(); i++){
ReceptenDefine recept;
recept = new ReceptenDefine();
JSONObject jRealObject = jArray.getJSONObject(i);
recept.setReceptnaam(jRealObject.getString("naam"));
recept.setReceptauthor(jRealObject.getString("id"));
recept.setReceptimageurl("http://www.crossfitswarm.com/wp-content/uploads/2013/03/food-photo-200x200.png");
recept.setReceptrating(jRealObject.getString("ingredienten"));
receptenList.add(recept);
}
return true;
}
} catch (JSONException | IOException e) {
e.printStackTrace();
}
return false;
}
@Override
protected void onPostExecute(Boolean result){
super.onPostExecute(result);
if(!result){
//Show message that data wasn't parsed
} else {
ReceptenAdapter adapter = new ReceptenAdapter(getApplicationContext(), R.layout.row, receptenList);
list.setAdapter(adapter);
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_recepten, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
ReceptenDefine
public class ReceptenDefine extends Recepten {
private String receptnaam;
private String receptauthor;
private String receptimageurl;
private String receptrating;
public ReceptenDefine(){
}
public String getReceptnaam() {
return receptnaam;
}
public void setReceptnaam(String receptnaam) {
this.receptnaam = receptnaam;
}
public String getReceptauthor() {
return receptauthor;
}
public void setReceptauthor(String receptauthor) {
this.receptauthor = receptauthor;
}
public String getReceptimageurl() {
return receptimageurl;
}
public void setReceptimageurl(String receptimageurl) {
this.receptimageurl = receptimageurl;
}
public String getReceptrating() {
return receptrating;
}
public void setReceptrating(String receptrating) {
this.receptrating = receptrating;
}
ReceptenAdapter
public class ReceptenAdapter extends ArrayAdapter<ReceptenDefine>{
ArrayList<ReceptenDefine> ArrayListRecepten;
int Resource;
Context context;
LayoutInflater vi;
public ReceptenAdapter(Context context, int resource, ArrayList<ReceptenDefine> objects) {
super(context, resource, objects);
ArrayListRecepten = objects;
Resource = resource;
this.context = context;
vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); //Verschillende items laten zien
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView == null){
//Eerste listview item wordt gemaakt
convertView = vi.inflate(Resource, null);
holder = new ViewHolder();
//Set all textview and imageview dingen
holder.listImage = (ImageView)convertView.findViewById(R.id.listImage);
holder.listAuthor = (TextView)convertView.findViewById(R.id.listAuthor);
holder.listName = (TextView)convertView.findViewById(R.id.listName);
holder.listRating = (TextView)convertView.findViewById(R.id.listRating);
//Zet het neer
convertView.setTag(holder);
} else {
//volgende list items, doe alles opnieuw zetten
holder = (ViewHolder)convertView.getTag();
}
new DownloadImageTask(holder.listImage).execute(ArrayListRecepten.get(position).getReceptimageurl());
holder.listName.setText(ArrayListRecepten.get(position).getReceptnaam());
holder.listAuthor.setText(ArrayListRecepten.get(position).getReceptauthor());
holder.listRating.setText(ArrayListRecepten.get(position).getReceptrating());
return convertView;
}
static class ViewHolder {
public ImageView listImage;
public TextView listName;
public TextView listAuthor;
public TextView listRating;
}
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImageTask(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return mIcon;
}
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
}
}
}