Java tutorial
/** * This is free and unencumbered software released into the public domain. * * Anyone is free to copy, modify, publish, use, compile, sell, or distribute * this software, either in source code form or as a compiled binary, for any * purpose, commercial or non-commercial, and by any means. * * In jurisdictions that recognize copyright laws, the author or authors of this * software dedicate any and all copyright interest in the software to the * public domain. We make this dedication for the benefit of the public at large * and to the detriment of our heirs and successors. We intend this dedication * to be an overt act of relinquishment in perpetuity of all present and future * rights to this software under copyright law. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * For more information, please refer to <http://unlicense.org/> */ package pffy.mobile.flax; import org.apache.http.protocol.HTTP; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.LinearLayout; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; /** * @name : FlaxActivity.java * @version : 1.35 (r35) * @updated : 2015-10-25 * @license : http://unlicense.org/ The Unlicense * @git : https://github.com/pffy/android-panera-bread * */ public class FlaxActivity extends Activity { // CONSTANTS public static final String CRLF = "\r\n"; public static final String SPACE = " "; public static final String COLONSPACE = ": "; public static final String DELIMITER = ";"; // Views private Spinner mSpinnerFoodCat; private Spinner mSpinnerFoodItem; private TextView mTextViewOutputNames; private TextView mTextViewOutputFacts; private LinearLayout mLinearLayoutApp; // Data private ArrayAdapter<String> mArrayAdapterFoodItems; private String[] mFoodFacts; private String mExportFacts; // Choices private int mFoodCatId = 0; private int mFoodItemId = 0; // Names and food facts private int[] mNames; private int[] mFacts; // Nutrient labels private int[] mNutrients; private int[] mTxts; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_flax); this.mLinearLayoutApp = (LinearLayout) findViewById(R.id.linearlayout_app); this.mSpinnerFoodCat = (Spinner) findViewById(R.id.spinner_foodcat); this.mSpinnerFoodItem = (Spinner) findViewById(R.id.spinner_fooditem); this.mTextViewOutputFacts = (TextView) findViewById(R.id.textview_output_foodfacts); this.mTextViewOutputNames = (TextView) findViewById(R.id.textview_output_foodname); this.mSpinnerFoodCat.setOnItemSelectedListener(mChoiceHandler); this.mSpinnerFoodItem.setOnItemSelectedListener(mChoiceHandler); this.mTextViewOutputFacts.setOnLongClickListener(mPokeHandler); this.mLinearLayoutApp.setOnLongClickListener(mPokeHandler); // Builds important stuff this.startUp(); } // OPTIONS MENU @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.flax, menu); return true; } // GETPREFS: Loads persistent data when user re-opens @Override protected void onResume() { super.onResume(); this.getPrefs(); } // SETPREFS: Saves persistent data when user clicks away (home or elsewhere) @Override protected void onPause() { super.onPause(); this.setPrefs(); } // SAVESTATE: saves instance state @Override protected void onSaveInstanceState(Bundle savedInstanceState) { super.onSaveInstanceState(savedInstanceState); savedInstanceState.putInt(getResources().getString(R.string.prefkey_int_foodcatid), this.mFoodCatId); savedInstanceState.putInt(getResources().getString(R.string.prefkey_int_fooditemid), this.mFoodItemId); savedInstanceState.putString(getResources().getString(R.string.prefkey_str_foodnames), this.getOutputNames()); savedInstanceState.putString(getResources().getString(R.string.prefkey_str_foodfacts), this.getOutputFacts()); } // GETSTATE: gets instance state @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); this.mFoodCatId = savedInstanceState.getInt(getResources().getString(R.string.prefkey_int_foodcatid)); this.mFoodItemId = savedInstanceState.getInt(getResources().getString(R.string.prefkey_int_fooditemid)); this.setOutputNames(savedInstanceState.getString(getResources().getString(R.string.prefkey_str_foodnames))); this.setOutputFacts(savedInstanceState.getString(getResources().getString(R.string.prefkey_str_foodfacts))); // Refreshes drop down menus this.mSpinnerFoodCat.setSelection(this.mFoodCatId); this.mSpinnerFoodItem.setSelection(this.mFoodItemId); } // HELPER METHODS // Gets persistent data private void getPrefs() { SharedPreferences shpref = this.getPreferences(Context.MODE_PRIVATE); this.mFoodCatId = shpref.getInt(getString(R.string.prefkey_int_foodcatid), 0); this.mFoodItemId = shpref.getInt(getString(R.string.prefkey_int_fooditemid), 0); this.setOutputNames(shpref.getString(getString(R.string.prefkey_str_foodnames), getResources().getStringArray(R.array.bsandwiches)[0])); this.setOutputFacts(shpref.getString(getString(R.string.prefkey_str_foodfacts), getResources().getStringArray(R.array.bsandwiches_details)[0])); // Refreshes drop down menus this.mSpinnerFoodCat.setSelection(this.mFoodCatId); this.mSpinnerFoodItem.setSelection(this.mFoodItemId); } // Sets persistent data private void setPrefs() { SharedPreferences shpref = this.getPreferences(Context.MODE_PRIVATE); SharedPreferences.Editor editor = shpref.edit(); editor.putInt(getString(R.string.prefkey_int_foodcatid), this.mFoodCatId); editor.putInt(getString(R.string.prefkey_int_fooditemid), this.mFoodItemId); editor.putString(getString(R.string.prefkey_str_foodnames), this.getOutputNames()); editor.putString(getString(R.string.prefkey_str_foodfacts), this.getOutputFacts()); editor.commit(); } // Returns menu item text private String getOutputNames() { return this.mTextViewOutputNames.getText().toString(); } // Returns nutrition facts text private String getOutputFacts() { return this.mTextViewOutputFacts.getText().toString(); } // Sets menu item text; returns this object for chaining private FlaxActivity setOutputNames(String str) { this.mTextViewOutputNames.setText(str); return this; } // Sets nutrition facts text; returns this object for chaining private FlaxActivity setOutputFacts(String str) { this.mTextViewOutputFacts.setText(str); return this; } // Maps the menu items and nutrition facts private void startUp() { // mCats and mFacts are parallel arrays // category keys this.mNames = new int[] { R.array.bsandwiches, R.array.bfavorites, R.array.souffles, R.array.bagels, R.array.creamcheese, R.array.artisanpastries, R.array.sweetrolls, R.array.scones, R.array.muffins, R.array.cakes, R.array.cookies, R.array.pastries, R.array.artisanbreads, R.array.specialtybreads, R.array.espresso, R.array.coffee, R.array.fruitsmoothies, R.array.frozendrinks, R.array.icedbeverages, R.array.bottledbeverages, R.array.softdrinks, R.array.juices, R.array.panini, R.array.sandwiches, R.array.flatbreadsandwiches, R.array.salads, R.array.dressings, R.array.brothbowls, R.array.pastas, R.array.soups, R.array.panerakidsalads, R.array.panerakidpastas, R.array.panerakidsoups, R.array.panerakidsandwiches, R.array.panerakidsides, R.array.sides }; // food facts keys this.mFacts = new int[] { R.array.bsandwiches_details, R.array.bfavorites_details, R.array.souffles_details, R.array.bagels_details, R.array.creamcheese_details, R.array.artisanpastries_details, R.array.sweetrolls_details, R.array.scones_details, R.array.muffins_details, R.array.cakes_details, R.array.cookies_details, R.array.pastries_details, R.array.artisanbreads_details, R.array.specialtybreads_details, R.array.espresso_details, R.array.coffee_details, R.array.fruitsmoothies_details, R.array.frozendrinks_details, R.array.icedbeverages_details, R.array.bottledbeverages_details, R.array.softdrinks_details, R.array.juices_details, R.array.panini_details, R.array.sandwiches_details, R.array.flatbreadsandwiches_details, R.array.salads_details, R.array.dressings_details, R.array.brothbowls_details, R.array.pastas_details, R.array.soups_details, R.array.panerakidsalads_details, R.array.panerakidpastas_details, R.array.panerakidsoups_details, R.array.panerakidsandwiches_details, R.array.panerakidsides_details, R.array.sides_details }; // parallel arrays for nutrient labels // CAL-FAT-SFAT-TFAT-CHOL-SALT-CARBS-FBR-SGR-PRO this.mNutrients = new int[] { R.string.nutrient_cal, R.string.nutrient_fat, R.string.nutrient_sfat, R.string.nutrient_tfat, R.string.nutrient_chol, R.string.nutrient_salt, R.string.nutrient_carbs, R.string.nutrient_fbr, R.string.nutrient_sgr, R.string.nutrient_pro }; this.mTxts = new int[] { R.string.txt_cal, R.string.txt_fat, R.string.txt_sfat, R.string.txt_tfat, R.string.txt_chol, R.string.txt_salt, R.string.txt_carbs, R.string.txt_fbr, R.string.txt_sgr, R.string.txt_pro }; } // Extracts nutrition facts from food item detail string private void extractNutritionFacts(String foodFacts) { String export = ""; String str = ""; String[] arr = foodFacts.split(DELIMITER); export += getString(R.string.txt_item) + COLONSPACE + arr[10]; for (int i = 0; i < this.mNutrients.length; i++) { str += padDetails(getString(this.mNutrients[i]), arr[i]); export += SPACE + getString(this.mTxts[i]) + COLONSPACE + arr[i]; } this.setOutputNames(arr[10]); this.setOutputFacts(str); this.mExportFacts = export; } // Formats and pads text string, lining the single-space fonts nicely private String padDetails(String str, String data) { return String.format("%-" + getResources().getInteger(R.integer.int_txtpadding) + "s", str) + COLONSPACE + data + CRLF; } // Shares nutrition facts as TXT short format private boolean sendDetailsByIntent() { if (this.mExportFacts.equals("") || this.mExportFacts == null) { // do not send empty files return false; } // boilerplate intent code Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); sendIntent.putExtra(Intent.EXTRA_TEXT, this.mExportFacts); sendIntent.setType(HTTP.PLAIN_TEXT_TYPE); startActivity(Intent.createChooser(sendIntent, getResources().getString(R.string.msg_shareto))); return true; } // Returns version info private String getVersionInfo() { PackageInfo info; String str = ""; try { info = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_META_DATA); str += "v" + info.versionName + " (r" + info.versionCode + ")"; } catch (NameNotFoundException nnfe) { str += "No version info."; } str += CRLF + getString(R.string.msg_authors); return str; } // EVENT LISTENERS // Clean, simple event-handling and processing // Handles options menu selections @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_about: Toast.makeText(getBaseContext(), this.getVersionInfo(), Toast.LENGTH_LONG).show(); return true; case R.id.action_share: this.sendDetailsByIntent(); return true; default: // nothing break; } return super.onOptionsItemSelected(item); } // Handles choices private AdapterView.OnItemSelectedListener mChoiceHandler = new AdapterView.OnItemSelectedListener() { private int mOldCatId = 0; @Override public void onItemSelected(AdapterView<?> av, View v, int pos, long id) { switch (av.getId()) { case R.id.spinner_foodcat: // category changed mFoodCatId = pos; if (mFoodCatId == this.mOldCatId) { mSpinnerFoodItem.setSelection(mFoodItemId); } try { mArrayAdapterFoodItems = new ArrayAdapter<String>(getBaseContext(), android.R.layout.simple_spinner_item, getResources().getStringArray(mNames[pos])); mArrayAdapterFoodItems.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); mSpinnerFoodItem.setAdapter(mArrayAdapterFoodItems); mFoodFacts = getResources().getStringArray(mFacts[pos]); } catch (Exception ex) { mArrayAdapterFoodItems = new ArrayAdapter<String>(getBaseContext(), android.R.layout.simple_spinner_item, getResources().getStringArray(R.array.bsandwiches)); mArrayAdapterFoodItems.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); mSpinnerFoodItem.setAdapter(mArrayAdapterFoodItems); mFoodFacts = getResources().getStringArray(R.array.bsandwiches_details); } // saves category for next time this.mOldCatId = mFoodCatId; break; case R.id.spinner_fooditem: // food item changed mFoodItemId = pos; extractNutritionFacts(mFoodFacts[pos]); break; default: // nothing break; } } @Override public void onNothingSelected(AdapterView<?> av) { // nothing } }; // Handles pokes private View.OnLongClickListener mPokeHandler = new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { switch (v.getId()) { case R.id.textview_output_foodfacts: sendDetailsByIntent(); return true; case R.id.linearlayout_app: openOptionsMenu(); return true; default: // nothing break; } return false; } }; }