Java tutorial
/** Copyright 2014 Reagan Lopez [This program is licensed under the "MIT License"] Please see the file LICENSE in the source distribution of this software for license terms */ package com.nike.plusgps.nikeplusgallery; import android.app.Activity; import android.app.ActivityManager; import android.app.ProgressDialog; import android.content.Context; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.os.Bundle; import android.util.DisplayMetrics; import android.util.Log; import android.util.LruCache; import android.view.Menu; import android.view.MenuItem; import android.widget.GridView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.Toast; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; /** * Main Activity has Async tasks to parse a JSON response and load it into SQLite. * In portrait mode, images and its titles are displayed in a grid view. * In landscape mode, images are displayed in a carousel. */ public class MainActivity extends Activity { ArrayList<FlickrFeed> flickrFeedList; // Container to hold the JSON images and titles FlickrFeedAdapter adapter; // Adapter to download the images and titles private static final float INITIAL_ITEMS_COUNT = 2.5F; // Number of items visible when the carousel is shown private LinearLayout carouselElement; // Carousel container layout private DBHelper dbHelper; // SQLite database instance private LruCache<String, Bitmap> mMemoryCache; private final Object mDiskCacheLock = new Object(); private boolean mDiskCacheStarting = true; private static final int DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10MB private static final String DISK_CACHE_SUBDIR = "thumbnails"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); dbHelper = new DBHelper(this); // Creates the database dbHelper.deleteAllResponse(); // Clears the JSON response cache dbHelper.deleteAllMedia(); // Clears the JSON images cache // Get memory class of this device, exceeding this amount will throw an // OutOfMemory exception. final int memClass = ((ActivityManager) getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass(); // Use 1/8th of the available memory for this memory cache. final int cacheSize = 1024 * 1024 * memClass / 8; mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { @Override protected int sizeOf(String key, Bitmap bitmap) { // The cache size will be measured in bytes rather than number of items. return bitmap.getByteCount(); } }; if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { setContentView(R.layout.activity_main_port); GridView view = (GridView) findViewById(R.id.gridView); flickrFeedList = new ArrayList<FlickrFeed>(); new JSONParser() .execute("http://api.flickr.com/services/feeds/photos_public.gne?tags=nike&format=json"); adapter = new FlickrFeedAdapter(getApplicationContext(), R.layout.single_elem_port, flickrFeedList, dbHelper, mMemoryCache); view.setAdapter(adapter); } else { setContentView(R.layout.activity_main_land); carouselElement = (LinearLayout) findViewById(R.id.carousel); // Compute width of a carousel item based on screen width and initial item count final DisplayMetrics displayMetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); final int imageWidth = (int) (displayMetrics.widthPixels / INITIAL_ITEMS_COUNT); ImageView imageItem; String imgURL; for (int i = 0; i < flickrFeedList.size(); ++i) { imageItem = new ImageView(this); imgURL = flickrFeedList.get(i).getMedia(); new DownloadImageTask(imageItem).execute(imgURL); imageItem.setLayoutParams(new LinearLayout.LayoutParams(imageWidth, imageWidth)); carouselElement.addView(imageItem); } } } /** * Handles the screen layouts based on the orientation. * The activity is not restarted when the orientation changes. */ public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); // In Portrait mode the grid view is displayed if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { setContentView(R.layout.activity_main_port); GridView view = (GridView) findViewById(R.id.gridView); adapter = new FlickrFeedAdapter(getApplicationContext(), R.layout.single_elem_port, flickrFeedList, dbHelper, mMemoryCache); view.setAdapter(adapter); } else { // In Landscape mode the carousel view is displayed setContentView(R.layout.activity_main_land); carouselElement = (LinearLayout) findViewById(R.id.carousel); // Compute width of a carousel item based on screen width and initial item count final DisplayMetrics displayMetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); final int imageWidth = (int) (displayMetrics.widthPixels / INITIAL_ITEMS_COUNT); // Fetches image url from SQLite cache ImageView imageItem; String imgURL; for (int i = 0; i < flickrFeedList.size(); ++i) { imageItem = new ImageView(this); imgURL = flickrFeedList.get(i).getMedia(); new DownloadImageTask(imageItem).execute(imgURL); imageItem.setLayoutParams(new LinearLayout.LayoutParams(imageWidth, imageWidth)); carouselElement.addView(imageItem); } } } /** * Async task to download the images. */ private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { ImageView bmImage; public DownloadImageTask(ImageView bmImage) { this.bmImage = bmImage; } @Override protected Bitmap doInBackground(String... strings) { String imgURL = strings[0]; Bitmap bm = null; bm = getBitmapFromMemCache(imgURL); // Gets bitmap from memory cache try { if (bm == null) { // Generates bitmap from the server InputStream in = new java.net.URL(imgURL).openStream(); bm = BitmapFactory.decodeStream(in); } addBitmapToMemoryCache(imgURL, bm); // Adds bitmap to memory cache. } catch (Exception e) { Log.e("Error", e.getMessage()); e.printStackTrace(); } return bm; } @Override protected void onPostExecute(Bitmap result) { bmImage.setImageBitmap(result); } } /** * Async task to read the JSON response from server. */ class JSONParser extends AsyncTask<String, Void, Boolean> { ProgressDialog dialog; @Override protected void onPreExecute() { super.onPreExecute(); dialog = new ProgressDialog(MainActivity.this); dialog.setMessage("Loading, please wait"); dialog.setTitle("Connecting server"); dialog.show(); dialog.setCancelable(false); } @Override protected Boolean doInBackground(String... strings) { try { HttpGet httppost = new HttpGet(strings[0]); HttpClient httpclient = new DefaultHttpClient(); HttpResponse response = httpclient.execute(httppost); int status = response.getStatusLine().getStatusCode(); if (status == 200) { HttpEntity entity = response.getEntity(); String strEntity = EntityUtils.toString(entity); String data = strEntity.substring(strEntity.indexOf("{"), strEntity.lastIndexOf(")")); dbHelper.insertResponse(data); // Insert response into SQLite cache JSONObject jobj = new JSONObject(data); JSONArray jarray = jobj.getJSONArray("items"); String img_url; String img_title; for (int i = 0; i < jarray.length(); i++) { JSONObject object = jarray.getJSONObject(i); FlickrFeed feed = new FlickrFeed(); img_url = (new JSONObject(object.getString("media"))).getString("m"); img_title = object.getString("title"); feed.setMedia(img_url); feed.setTitle(img_title); flickrFeedList.add(feed); dbHelper.insertMedia(img_url, img_title); // Insert image path and title into SQLite Cache //Toast.makeText(getApplicationContext(), String.valueOf(dbHelper.countMedia()), Toast.LENGTH_SHORT).show(); } return true; } } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } return false; } @Override protected void onPostExecute(Boolean result) { dialog.cancel(); adapter.notifyDataSetChanged(); if (result == false) Toast.makeText(getApplicationContext(), "Unable to fetch data from server", Toast.LENGTH_LONG) .show(); } } public void addBitmapToMemoryCache(String key, Bitmap bitmap) { if (getBitmapFromMemCache(key) == null) { mMemoryCache.put(key, bitmap); } } public Bitmap getBitmapFromMemCache(String key) { return (Bitmap) mMemoryCache.get(key); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, 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(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }