Java tutorial
package de.dhbw.advisory.recipe; import android.content.Intent; import android.content.res.AssetManager; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.Matrix; import android.net.Uri; import android.os.Bundle; import android.support.design.widget.Snackbar; import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.support.v4.app.Fragment; import android.widget.ImageView; import android.widget.TableLayout; import android.widget.TableRow; import android.widget.TextView; import android.os.AsyncTask; import android.content.Context; import android.widget.TableRow.LayoutParams; import java.io.IOException; import java.io.InputStream; import android.graphics.BitmapFactory; import android.app.ProgressDialog; import android.widget.Toast; import com.google.api.client.http.GenericUrl; import com.google.api.client.http.HttpHeaders; import com.google.api.client.http.HttpRequest; import com.google.api.client.http.HttpRequestFactory; import com.google.api.client.http.HttpResponse; import com.google.api.client.http.HttpTransport; import com.google.api.client.http.javanet.NetHttpTransport; import com.google.common.io.CharStreams; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.InputStreamReader; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import java.util.Properties; import de.dhbw.advisory.R; import de.dhbw.advisory.common.AsyncTaskResult; public class RecipeFragment extends Fragment { //Ladebildschirm private ProgressDialog _alertDialog; //UI-Elemente protected TextView _rezepteberschrift = null; protected TextView _rezepteTitel = null; protected TextView _rezepteAnleitung = null; protected TableLayout _rezepteZutatenliste = null; protected ImageView _rezepteIcon = null; protected TextView _rezepteZutaten = null; protected TextView _rezepteRezepte = null; protected TableRow _rezepteTableRow = null; //Snackbar private Snackbar _snackbar; //Apikey private String apiKey; public DisplayMetrics metrics; @Override public void onAttach(Context context) { Log.i("Recipe-Fragment - onAttach", "Methode gestartet"); super.onAttach(context); //Der Developer key wird spter aus der properties-Datei ausgelesen Properties properties = new Properties(); try { //Hier wird der API-Key geladen AssetManager assetManager = context.getAssets(); InputStream inputStream = assetManager.open("apikey.properties"); properties.load(inputStream); apiKey = properties.getProperty("spoonacular.apikey"); } catch (IOException e) { //Falls das Fragment nicht geladen werden konnte Toast.makeText(context, "Fragment konnte nicht geladen werden", Toast.LENGTH_SHORT).show(); } Log.i("Recipe-Fragment - onAttach", "Methode beendet"); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Log.i("RecipeFragment - onCreate", "Methode gestartet"); View view = inflater.inflate(R.layout.fragment_rezepte, container, false); metrics = this.getResources().getDisplayMetrics(); //Ladebildschirm einfgen _alertDialog = new ProgressDialog(getContext()); _alertDialog.setMessage(getResources().getString(R.string.loader)); _alertDialog.setCancelable(false); _alertDialog.show(); //Referenzen der Textviews abfragen _rezepteTitel = (TextView) view.findViewById(R.id.Rezepte_Titel); _rezepteberschrift = (TextView) view.findViewById(R.id.Rezepte_berschrift); _rezepteAnleitung = (TextView) view.findViewById(R.id.rezepte_Rezept_Text); _rezepteZutatenliste = (TableLayout) view.findViewById(R.id.rezepte_Zutatenliste); _rezepteIcon = (ImageView) view.findViewById(R.id.rezepte_Icon); _rezepteZutaten = (TextView) view.findViewById(R.id.rezepte_Zutaten); _rezepteRezepte = (TextView) view.findViewById(R.id.rezepte_Rezept); _rezepteTableRow = (TableRow) view.findViewById(R.id.rezepte_TableRow); //Titel aktualisieren int h = actualHour(); _rezepteberschrift.setText(getEssensTyp(h)); //Hier wird berprft, ob eine Internetverbindung vorhanden ist, falls diese nicht vorhanden ist wird eine Meldung ausgegeben if (AppStatus.getInstance(this.getContext()).isOnline() == false) { _snackbar = Snackbar.make(container, "Keine Internetverbindung!", Snackbar.LENGTH_LONG); View sbView = _snackbar.getView(); TextView textView = (TextView) sbView.findViewById(android.support.design.R.id.snackbar_text); textView.setTextColor(Color.WHITE); _snackbar.show(); } //API Aufruf starten und Felder aktualisieren RecipeAPI mat = new RecipeAPI(this.getContext()); mat.execute(getEssensTypAnfrage(h)); Log.i("RecipeFragment - onCreate", "Methode beendet"); return view; } @Override public void onPause() { Log.i("RecipeFragment - onPause", "Methode gestartet/ beendet"); super.onPause(); } /** * Diese Methode hidet den Progress Dialog */ public void cancelProgressDialog() { Log.i("RecipeFragment - cancelProgressDialog", "Methode gestartet/ beendet"); _alertDialog.dismiss(); } /** * Diese Methode liest die aktuelle Stundenzeit anhand der Systemzeit aus * * @return gibt die aktuelle Stundenzeit zurck */ public int actualHour() { Log.i("RecipeFragment - actualHour", "Methode gestartet"); int hh; Calendar kalendar = Calendar.getInstance(); //Umstellung des Zeitformat nur auf die Stunden SimpleDateFormat zeitformatH = new SimpleDateFormat("HH"); String h = zeitformatH.format(kalendar.getTime()); hh = Integer.parseInt(h); Log.i("RecipeFragment - actualHour", "Methode beendet"); return hh; } /** * Diese Methode ermittelt anhand der bergebenen Zeit den Titel des Fragments * @param hh gibt die aktuelle Stundenzeit an * @return gibt den Essentyp fr den Titel an */ public String getEssensTyp(int hh) { Log.i("RecipeFragment - getEssensTyp", "Methode gestartet"); //breakfast 6-9 //appetizer 10-11 //main course 12-14 //side dish 15 //dessert 16 //main course 17-21 //salad 22-23 //soup 24-5 String typ; if (hh == 24 || hh <= 5) { //Soup typ = "ihre Suppe"; } else if (hh >= 6 && hh <= 9) { //Breakfast typ = "ihr Frhstck"; } else if (hh >= 10 && hh <= 11) { //Appetizer typ = "ihr Appetizer"; } else if (hh >= 12 && hh <= 14 || hh >= 17 && hh <= 21) { //Main Course typ = "ihr Hauptgericht"; } else if (hh == 15) { //side dish typ = "ihr kleiner Happen"; } else if (hh == 16) { //Dessert typ = "ihr Dessert"; } else if (hh >= 22 && hh <= 23) { //Salad typ = "ihr Salat"; } else { //Fehler typ = "Fehler"; } String r; if (typ == "Fehler") { r = typ; } else r = "Hier " + typ + "!"; Log.i("RecipeFragment - getEssensTyp", "Methode beendet"); return r; } /** * Diese Methode erstellt den Typ des Rezepts fr den AI Aufruf * @param hh die aktuelle Stundenzeit * @return gibt den Typ des Essens zurck (fr den API Parameter typ) */ public String getEssensTypAnfrage(int hh) { Log.i("RecipeFragment - getEssensTypAnfrage", "Methode gestartet"); //breakfast 6-9 //appetizer 10-11 //main course 12-14 //side dish 15 //dessert 16 //main course 17-21 //salad 22-23 //soup 24-5 String typ; if (hh == 24 || hh <= 5) { //Soup typ = "soup"; } else if (hh >= 6 && hh <= 9) { //Breakfast typ = "breakfast"; } else if (hh >= 10 && hh <= 11) { //Appetizer typ = "appetizer"; } else if (hh >= 12 && hh <= 14 || hh >= 17 && hh <= 21) { //Main Course typ = "main course"; } else if (hh == 15) { //side dish typ = "side dish"; } else if (hh == 16) { //Dessert typ = "dessert"; } else if (hh >= 22 && hh <= 23) { //Salad typ = "salad"; } else { //Fehler typ = "Fehler!"; } Log.i("RecipeFragment - getEssensTypAnfrage", "Methode beendet"); return typ; } /** * Diese Klasse bernimmt den Abruf eines Bildes und setzt dieses in den entsprechenden ImageView ein */ public class GetImage extends AsyncTask<String, String, Bitmap> { protected Context context; GetImage(Context context) { super(); this.context = context; } /** * Hier wird das Bild in einem Async Task aufgerufen * @param url die URL von der das Bild abgerufen werden soll * @return gibt das Bild in Form einer Bitmap zurck */ @Override protected Bitmap doInBackground(String... url) { Log.i("GetImage - doInBackground", "Methode gestartet"); Bitmap icon = null; if (AppStatus.getInstance(context).isOnline()) { //Internetverbindung aktiv Log.i("GetImage - DoInBackground", "Internetverbindung aktiv"); try { InputStream in = new java.net.URL(url[0]).openStream(); icon = BitmapFactory.decodeStream(in); } catch (Exception e) { Log.e("Error", e.getMessage()); } Log.i("GetImage - DoInBackground", "Methode beendet"); return icon; } else { //Internetverbindung nicht aktiv; gibt dann ein leeres Bild zurck Log.i("GetImage - DoInBackground", "Internetverbindung nicht aktiv"); Log.i("GetImage - doInBackground", "Methode beendet"); return icon; } } /** * Die Methode skaliert das erhaltene Bild auf die komplette Breite des CardViews und setzt dieses anschlieend darein * @param icon das zu setzende Bild */ @Override protected void onPostExecute(Bitmap icon) { Log.i("GetImage - onPostExecute", "Methode gestartet"); if (icon != null) { //Es ist ein nicht fehlerhaftes Bild angekommen //Bildbreite so breit wie die TableRow (=Breite CardView) setzten int bildbreite = _rezepteTableRow.getWidth(); int breite_alt = icon.getWidth(); int hoehe_alt = icon.getHeight(); //Das Seitenverhltnis wird beibehalten double skalierung = ((double) hoehe_alt) / ((double) breite_alt); int bildhoehe = (int) (bildbreite * skalierung); float scaleWidth = ((float) bildbreite) / breite_alt; float scaleHeight = ((float) bildhoehe) / hoehe_alt; Matrix matrix = new Matrix(); matrix.postScale(scaleWidth, scaleHeight); Bitmap resizedImage = Bitmap.createBitmap(icon, 0, 0, breite_alt, hoehe_alt, matrix, false); _rezepteIcon.setImageBitmap(resizedImage); _rezepteIcon.setImageAlpha(90); } else { //Das Bild ist fehlerhaft } cancelProgressDialog(); Log.i("GetImage - onPostExecute", "Methode beendet"); } } /** * In dieser Klasse wird der API Aufruf durchgefhrt */ public class RecipeAPI extends AsyncTask<String, String, AsyncTaskResult<?>> { protected Context context; RecipeAPI(Context context) { super(); this.context = context; } /** * Diese Methode ruft die Daten aus der API * @param params * @return gibt eine ArrayList zurck die alle bentigten Infos enthlt */ @Override protected AsyncTaskResult<?> doInBackground(String... params) { Log.i("Recipe API - doInBackground ", "Methode begonnen"); ArrayList erg; String typ = params[0]; try { //Hier wird der API Aufruf gemacht String jsonResponseRecipeSearch = getRecipe(typ); //Hier wird geparset erg = parseRecipe(jsonResponseRecipeSearch); Log.i("Recipe API - doInBackground ", "Methode beendet"); return new AsyncTaskResult(erg); } catch (Exception e) { try { //Keine Internetverbindung, daher wird eine gespeicherte JSON weitergegeben Log.i("Recipe API - doInBackground ", "Keine Internetverbindung"); Log.i("Recipe API - doInBackground", "Fehler: " + e.getMessage()); RecipeExample example = new RecipeExample(); Log.i("Recipe API - doInBackground ", "Methode beendet"); return new AsyncTaskResult(parseRecipe(example.getExampleJsonString(typ))); } catch (Exception f) { Log.i("Recipe API - doInBackground ", "Fehler: " + e.getMessage()); Log.i("Recipe API - doInBackground ", "Methode beendet"); return new AsyncTaskResult(f); } } } /** * Diese Methode setzt die aus der API erhaltenenn Informationen in die Views ein * @param asyncTaskResult die Informationen die eingesetzt werden sollen (ArrayList) */ @Override protected void onPostExecute(AsyncTaskResult asyncTaskResult) { Log.i("Recipe API - onPostExecute", "Methode begonnen"); if (asyncTaskResult.isSuccessful()) { Log.i("onPostExecute", "AsynTaskResult ist successfull"); final List ergebnis = asyncTaskResult.getResult(); //Titel setzten _rezepteTitel.setText(ergebnis.get(0).toString()); //Rezeptanleitung setzen _rezepteAnleitung.setText(ergebnis.get(2).toString()); //Hier wird das Bild abgerufen GetImage img = new GetImage(context); img.execute((String) ergebnis.get(3)); //Mit Klick auf das Rezepte Bild ffnet sich der Link des Rezepts _rezepteIcon.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String url = ergebnis.get(4).toString(); Intent i = new Intent(Intent.ACTION_VIEW); i.setData(Uri.parse(url)); startActivity(i); } }); //Zutaten bekommen String[][] zutaten = (String[][]) ergebnis.get(1); //TableRow & TextView Arrays erstellen TableRow[] tr = new TableRow[zutaten.length]; TextView[] tv_ing = new TextView[zutaten.length]; TextView[] tv_amount = new TextView[zutaten.length]; //Legt ein einheitliches Design fr die Zutaten fest LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); params.weight = 1f; //Zutaten in die Liste setzen for (int i = 0; i < zutaten.length; i++) { tr[i] = new TableRow(context); tv_ing[i] = new TextView(context); tv_amount[i] = new TextView(context); tv_ing[i].setLayoutParams(params); tv_ing[i].setTextColor(Color.BLACK); tv_ing[i].setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12); tv_ing[i].setText("" + zutaten[i][0] + ":"); tv_amount[i].setLayoutParams(params); tv_amount[i].setTextColor(Color.BLACK); tv_amount[i].setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12); tv_amount[i].setText("" + zutaten[i][1] + " " + zutaten[i][2]); tr[i].setPadding(0, 5, 0, 5); tr[i].addView(tv_ing[i]); tr[i].addView(tv_amount[i]); _rezepteZutatenliste.addView(tr[i]); } //Titel Zubereitung und Zutaten setzen _rezepteRezepte.setText("Zubereitung:"); _rezepteZutaten.setText("Zutaten:"); _rezepteZutatenliste.refreshDrawableState(); } else { Log.i("onPostExecute", "AsynTaskResult ist nicht successfull"); _rezepteTitel.setText("Bitte versuchen sie es spter erneut! :)"); } Log.i("onPostExecute", "Methode beendet"); cancelProgressDialog(); Log.i("Recipe API - onPostExecute", "Methode beendet"); } /** * * Die Methode macht die HTTP Anfrage an die API * * @param typ Gibt an nach welchem Typ gesucht wird (Mittagessen, Lunch, Suppe,..) * @return gibt den HTTP Request zurck * @throws Exception */ protected String getRecipe(String typ) throws Exception { Log.i("Recipe API - getRecipe ", "Methode begonnen"); if (AppStatus.getInstance(context).isOnline()) { Log.i("getRecipe ", "Internetverbindung vorhanden"); //1. Request Factory holen HttpTransport httpTransport = new NetHttpTransport(); HttpRequestFactory requestFactory = httpTransport.createRequestFactory(); //2. Url hinzufgen GenericUrl url = new GenericUrl( "https://spoonacular-recipe-food-nutrition-v1.p.mashape.com/recipes/random"); url.put("limitLicense", "false"); url.put("number", "1"); url.put("tags", "" + typ); url.put("measure", "metric"); //3. Request absetzen HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.set("X-Mashape-Key", apiKey); HttpRequest request = requestFactory.buildGetRequest(url); request.setHeaders(httpHeaders); HttpResponse httpResponse = request.execute(); String jsonResponseString = ""; try { InputStream inputStream = httpResponse.getContent(); jsonResponseString = CharStreams.toString(new InputStreamReader(inputStream, "UTF-8")); } finally { httpResponse.disconnect(); } Log.i("Recipe API - getRecipe ", "Methode beendet"); return jsonResponseString; } else { Log.i("getRecipe ", "Internetverbindung nicht vorhanden"); Log.i("Recipe API - getRecipe ", "Methode beendet"); throw new Exception(); } } /** * * Diese Methode parsed die Http Antwort der RecipeSearch Methode * * @param jsonString RecipeSearch Http Antwort als String parsen * @return * @throws JSONException */ protected ArrayList parseRecipe(String jsonString) throws JSONException { Log.i("Recipe API - parseRecipe", "Methode begonnen"); //Eigentliches parsen JSONObject jsonObject = new JSONObject(jsonString); //Wichtigsten Inhalt entnehmen JSONArray jsonArray = jsonObject.getJSONArray("recipes"); JSONObject i = jsonArray.getJSONObject(0); //Rezept parsen (aus den verschiedenen Schritten des Rezepts JSONArray recipe = i.getJSONArray("analyzedInstructions").getJSONObject(0).getJSONArray("steps"); String recipeString = ""; //Hier wird das eigentliche Rezept entnommen for (int l = 0; l < recipe.length(); l++) { recipeString = recipeString + recipe.getJSONObject(l).getString("step"); recipeString = recipeString + "\n"; } JSONArray ingredients = i.getJSONArray("extendedIngredients"); int length = ingredients.length(); //[][0] = name //[][1] = amount //[][2] = unit String[][] ing = new String[length][3]; //Zutatenliste erstellen for (int x = 0; x < length; x++) { ing[x][0] = ingredients.getJSONObject(x).getString("name"); ing[x][1] = ingredients.getJSONObject(x).getString("amount"); ing[x][2] = ingredients.getJSONObject(x).getString("unit"); } //Titel, Bild und Rezept URL parsen String title = i.getString("title"); String img_url = i.getString("image"); String recipe_url = i.getString("sourceUrl"); ArrayList<Object> information = new ArrayList<>(); //Infos in die ArrayList setzen information.add(0, title); information.add(1, ing); information.add(2, recipeString); information.add(3, img_url); information.add(4, recipe_url); Log.i("Recipe API - parseRecipe", "Methode beendet"); return information; } } }