Java tutorial
/* BalticApp, for studying and tracking the condition of the Baltic sea and Gulf of Finland throug user submissions. Copyright (C) 2016 Daniel Zakharin, LuKe This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/> or the beginning of MainActivity.java file. */ package com.luke.lukef.lukeapp.tools; import android.Manifest; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.location.Location; import android.location.LocationManager; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Build; import android.provider.Settings; import android.support.v4.content.ContextCompat; import android.util.Base64; import android.util.Log; import com.luke.lukef.lukeapp.model.Category; import com.luke.lukef.lukeapp.model.Link; import com.luke.lukef.lukeapp.model.Rank; import com.luke.lukef.lukeapp.model.SessionSingleton; import com.luke.lukef.lukeapp.model.Submission; import com.luke.lukef.lukeapp.model.UserFromServer; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; /** * Utility methods to be used from anywhere in the app. Mainly parsing {@link JSONObject JSONObjects} and {@link JSONArray JSONArrays} * into usable objects. */ public class LukeUtils { private static final String TAG = "LukeUtils"; private static final String noInternet = "The Baltic app requires an Internet Connection to work. Enable Internet now?"; private static final String noGps = "Making a submission requires GPS to be enabled. Enable GPS now?"; /** * Turns a Bitmap object into a Base64 type String. * * @param bitmap Bitmap that should be parsed. * @return String of the Bitmap in Base64 enconding. */ public static String bitmapToBase64String(Bitmap bitmap) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream); byte[] byteArray = byteArrayOutputStream.toByteArray(); return Base64.encodeToString(byteArray, Base64.DEFAULT); } /** * Parses submissions from JSONArray. * * @param jsonArray JSONArray with Submission JSONObjects. * @return ArrayList of the Submission objects. * @throws JSONException */ static ArrayList<Submission> parseSubmissionsFromJsonArray(JSONArray jsonArray) throws JSONException { ArrayList<Submission> submissions = new ArrayList<>(); for (int i = 0; i < jsonArray.length(); i++) { JSONObject jsonObject = jsonArray.getJSONObject(i); Submission submission = parseSubmissionFromJsonObject(jsonObject); submissions.add(submission); } return submissions; } /** * Parses a JSONObject into a Submission object * @param jsonObject JSONObject to be parsed * @return Submission object * @throws JSONException */ public static Submission parseSubmissionFromJsonObject(JSONObject jsonObject) throws JSONException { Submission submission = new Submission(); if (jsonObject.has("id")) { submission.setSubmissionId(jsonObject.getString("id")); } if (jsonObject.has("image_url")) { submission.setImageUrl(jsonObject.getString("image_url")); } if (jsonObject.has("title")) { submission.setTitle(jsonObject.getString("title")); } if (jsonObject.has("description")) { submission.setDescription(jsonObject.getString("description")); } if (jsonObject.has("submittedId")) { submission.setSubmitterId(jsonObject.getString("submitterId")); } if (jsonObject.has("date")) { submission.setDate(jsonObject.getString("date")); } if (jsonObject.has("categoryId")) { submission.setSubmissionCategoryList(parseStringsFromJsonArray(jsonObject.getJSONArray("categoryId"))); } if (jsonObject.has("latitude") && jsonObject.has("longitude")) { Location location = new Location("jea"); location.setLatitude(jsonObject.getDouble("latitude")); location.setLongitude(jsonObject.getDouble("longitude")); submission.setLocation(location); } if (jsonObject.has("submitterId")) { submission.setSubmitterId(jsonObject.getString("submitterId")); } return submission; } /** * Parses all strings inside the given JSONArray and adds them into a list. * * @param jsonArrayToParse The JSONArray that should be parsed. * @return ArrayList of Strings. */ private static ArrayList<String> parseStringsFromJsonArray(JSONArray jsonArrayToParse) { ArrayList<String> strings = new ArrayList<>(); try { for (int i = 0; i < jsonArrayToParse.length(); i++) { String jsonString = jsonArrayToParse.getString(i); strings.add(jsonString); } } catch (JSONException e) { Log.e(TAG, "parseStringsFromJsonArray: ", e); } return strings; } /** * Parses date from MS to the defined format * * @param submission_date The amount of milliseconds from the Jan 1, 1970 GMT to the desired date * @return Date as String in defined format */ public static String parseDateFromMillis(long submission_date) { Date date = new Date(submission_date); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.CHINA); format.applyPattern("hh:mm dd/MM/yyyy"); return format.format(date); } /** * Parses the given String into a date object and outputs it in a different pattern. * * @param dateToParse Date as a String in the following pattern: <b>yyyy-MM-dd'T'HH:mm:ss.SSS'Z'</b>. * @return The given date, but in the following format: <b>hh:mm dd/MM/yyyy</b>. */ public static String parseDateFromString(String dateToParse) { try { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault()); Date date; date = format.parse(dateToParse); format.applyPattern("hh:mm dd/MM/yyyy"); return format.format(date); } catch (ParseException e) { Log.e(TAG, "parseDateFromString: ", e); return null; } } /** * Checks the current GPS status, if GPS is not enabled then calls * {@link LukeUtils#alertDialogBuilder(Context, String, String)} to create a prompt for the user * to enable GPS. * * @param context Context, needed to create the alert. * @return <b>true</b> if the GPS is enabled, <b>false</b> if it's not. */ public static boolean checkGpsStatus(Context context) { final LocationManager manager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { alertDialogBuilder(context, noGps, android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS); return false; } else { return true; } } /** * Checks the current Internet status, if Internet is not enabled then calls * {@link LukeUtils#alertDialogBuilder(Context, String, String)} to create a prompt for the user * to enable Internet. * * @param context Context, needed to create the alert. * @return <b>true</b> if the GPS is enabled, <b>false</b> if it's not. */ public static boolean checkInternetStatus(Context context) { ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo netInfo = cm.getActiveNetworkInfo(); if (netInfo != null && netInfo.isConnectedOrConnecting()) { return true; } else { alertDialogBuilder(context, noInternet, Settings.ACTION_WIRELESS_SETTINGS); return false; } } /** * Creates an alert with <b>Yes</b> and <b>No</b> buttons. * * @param context Context, needed to start the given activity. * @param alertText The text to show in the alert. * @param settings The required android.provider.settings to open if user clicks <b>Yes</b>. */ private static void alertDialogBuilder(final Context context, String alertText, final String settings) { final AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setMessage(alertText).setCancelable(false) .setPositiveButton("Yes", new DialogInterface.OnClickListener() { public void onClick(@SuppressWarnings("unused") final DialogInterface dialog, @SuppressWarnings("unused") final int id) { context.startActivity(new Intent(settings)); } }).setNegativeButton("No", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); final AlertDialog alert = builder.create(); alert.show(); } /** * Picks out Category id's from a Submission object, and returns an array of Category objects corresponding to these id's * @param submission submissions whose categories needs to be returned * @return Arraylist of Category objects */ public static ArrayList<Category> getCategoryObjectsFromSubmission(Submission submission) { ArrayList<Category> categories = new ArrayList<>(); for (String s : submission.getSubmissionCategoryList()) { for (Category c : SessionSingleton.getInstance().getCategoryList()) { if (c.getId().equals(s)) { categories.add(c); } } } return categories; } /** * Parses {@link com.luke.lukef.lukeapp.model.Category} objects from the provided <code>JSONArray</code>. * Compares the fetched categories to the existing categories, adds new discards old. * * @param jsonArr The JSONArray fetched from server. */ public static ArrayList<Category> getCategoryObjectsFromJsonArray(JSONArray jsonArr) throws JSONException { ArrayList<Category> tempCategoryList = new ArrayList<>(); for (int i = 0; i < jsonArr.length(); i++) { JSONObject jsonCategory = jsonArr.getJSONObject(i); // check that the object has ID tag if (jsonCategory.has("id")) { Boolean found = false; // loop through the SessionSingleton's Categories list and see if the category is already there for (Category ca : SessionSingleton.getInstance().getCategoryList()) { if (ca.getId().equals(jsonCategory.getString("id"))) { found = true; } } // if the category doesn't exist yet on the list, then create it and add it to temp list if (!found) { Category c = new Category(); c.setId(jsonCategory.getString("id")); if (jsonCategory.has("description")) { c.setDescription(jsonCategory.getString("description")); } else { c.setDescription("No description"); } if (jsonCategory.has("title")) { c.setTitle(jsonCategory.getString("title")); } else { c.setTitle("No title"); } if (jsonCategory.has("positive")) { c.setPositive(jsonCategory.getBoolean("positive")); } Bitmap bitmap = null; if (jsonCategory.has("image_url")) { String imageUrl = jsonCategory.getString("image_url"); try { InputStream in = new URL(imageUrl).openStream(); bitmap = BitmapFactory.decodeStream(in); } catch (MalformedURLException e) { // Error downloading / parsing the image, setting to default bitmap = null;//BitmapFactory.decodeResource(ContextCompat.getDrawable(context, R.drawable.no_category_image)); } catch (IOException e) { Log.e(TAG, "parseCategories: IOException ", e); bitmap = null;//BitmapFactory.decodeResource(getResources(), R.drawable.no_category_image); } } else { // there was no image for the category, setting default bitmap = null;//BitmapFactory.decodeResource(getResources(), R.drawable.no_category_image); } c.setImage(bitmap); tempCategoryList.add(c); } } } return tempCategoryList; } /** * Parses Link objects from a JSONArray * @param jsonArr JSONArray from which to parse Links * @return Arraylist of Link objects * @throws JSONException */ public static List<Link> parseLinksFromJsonArray(JSONArray jsonArr) throws JSONException { ArrayList<Link> tempLinkList = new ArrayList<>(); for (int i = 0; i < jsonArr.length(); i++) { JSONObject jsonLink = jsonArr.getJSONObject(i); // check that the object has ID tag if (jsonLink.has("id")) { Link link = new Link(); link.setId(jsonLink.getString("id")); if (jsonLink.has("description")) { link.setDescription(jsonLink.getString("description")); } else { link.setDescription(""); } if (jsonLink.has("title")) { link.setTitle(jsonLink.getString("title")); } else { link.setTitle("No title"); } if (jsonLink.has("link")) { link.setLink(jsonLink.getString("link")); } else { link.setLink(""); } if (jsonLink.has("active")) { link.setActive(jsonLink.getBoolean("active")); } else { link.setActive(false); } if (jsonLink.has("done")) { JSONArray doneArray = jsonLink.getJSONArray("done"); link.setDone(parseStringsFromJsonArray(doneArray)); } else { link.setDone(null); } tempLinkList.add(link); } else { } } return tempLinkList; } /** * Parses User objects from JSONObject * @param jsonObject JSONObject from which to parse Users * @return User object * @throws JSONException */ public static UserFromServer parseUserFromJsonObject(JSONObject jsonObject) throws JSONException { UserFromServer userFromServer = new UserFromServer(); if (jsonObject.has("image_url")) { userFromServer.setImageUrl(jsonObject.getString("image_url")); } if (jsonObject.has("id")) { userFromServer.setId(jsonObject.getString("id")); } if (jsonObject.has("username")) { userFromServer.setUsername(jsonObject.getString("username")); } if (jsonObject.has("score")) { userFromServer.setScore(jsonObject.getInt("score")); } if (jsonObject.has("rankingId")) { userFromServer.setRankId(jsonObject.getString("rankingId")); } if (jsonObject.has("score")) { userFromServer.setScore(jsonObject.getInt("score")); } return userFromServer; } /** * Parses Rank objects from an JSONArray * @param jsonArray JSONArray from which to parse Ranks * @return Arraylist of Rank objects * @throws JSONException */ public static ArrayList<Rank> parseRanksFromJsonArray(JSONArray jsonArray) throws JSONException { ArrayList<Rank> ranks = new ArrayList<>(); for (int i = 0; i < jsonArray.length(); i++) { JSONObject jsonObject = jsonArray.getJSONObject(i); Rank rank = new Rank(); if (jsonObject.has("image_url")) { rank.setImageUrl(jsonObject.getString("image_url")); } if (jsonObject.has("id")) { rank.setId(jsonObject.getString("id")); } if (jsonObject.has("title")) { rank.setTitle(jsonObject.getString("title")); } if (jsonObject.has("score")) { rank.setScoreRequirement(jsonObject.getInt("score")); } if (jsonObject.has("description")) { rank.setDescription(jsonObject.getString("description")); } ranks.add(rank); } return ranks; } }