From 65c1db9dc23517ceff0e11e767585de330f70964 Mon Sep 17 00:00:00 2001 From: Joe Robinson Date: Mon, 4 Aug 2014 02:17:22 +0100 Subject: Added partially working image viewer with paging --- app/src/main/AndroidManifest.xml | 16 +- .../co/blatech/blaupload/BlauploadApplication.java | 50 ++++ .../co/blatech/blaupload/HomeScreenFragment.java | 21 +- .../java/uk/co/blatech/blaupload/ImagePager.java | 85 +++++++ .../blatech/blaupload/ui/DepthPageTransformer.java | 41 ++++ .../co/blatech/blaupload/ui/ImagePagerAdapter.java | 66 +++++ .../blaupload/ui/NetworkCacheableImageView.java | 271 +++++++++++++++++++++ .../uk/co/blatech/blaupload/ui/ZoomViewPager.java | 75 ++++++ .../uk/co/blatech/blaupload/util/ImageLoader.java | 54 +++- app/src/main/res/layout/activity_image_pager.xml | 16 ++ app/src/main/res/layout/activity_image_viewer.xml | 7 + app/src/main/res/layout/fragment_image_viewer.xml | 13 + app/src/main/res/menu/image_pager.xml | 8 + app/src/main/res/menu/image_viewer.xml | 8 + app/src/main/res/values/strings.xml | 3 + 15 files changed, 722 insertions(+), 12 deletions(-) create mode 100644 app/src/main/java/uk/co/blatech/blaupload/BlauploadApplication.java create mode 100644 app/src/main/java/uk/co/blatech/blaupload/ImagePager.java create mode 100644 app/src/main/java/uk/co/blatech/blaupload/ui/DepthPageTransformer.java create mode 100644 app/src/main/java/uk/co/blatech/blaupload/ui/ImagePagerAdapter.java create mode 100644 app/src/main/java/uk/co/blatech/blaupload/ui/NetworkCacheableImageView.java create mode 100644 app/src/main/java/uk/co/blatech/blaupload/ui/ZoomViewPager.java create mode 100644 app/src/main/res/layout/activity_image_pager.xml create mode 100644 app/src/main/res/layout/activity_image_viewer.xml create mode 100644 app/src/main/res/layout/fragment_image_viewer.xml create mode 100644 app/src/main/res/menu/image_pager.xml create mode 100644 app/src/main/res/menu/image_viewer.xml (limited to 'app/src') diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2700bb3..0b63b69 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,8 +1,11 @@ - + + + + + + + + + + diff --git a/app/src/main/java/uk/co/blatech/blaupload/BlauploadApplication.java b/app/src/main/java/uk/co/blatech/blaupload/BlauploadApplication.java new file mode 100644 index 0000000..518eff8 --- /dev/null +++ b/app/src/main/java/uk/co/blatech/blaupload/BlauploadApplication.java @@ -0,0 +1,50 @@ +package uk.co.blatech.blaupload; + +import android.app.Application; +import android.content.Context; +import android.os.Environment; +import android.util.Log; + +import java.io.File; + +import uk.co.senab.bitmapcache.BitmapLruCache; + +public class BlauploadApplication extends Application { + + private BitmapLruCache mCache; + + @Override + public void onCreate() { + super.onCreate(); + + File cacheLocation; + + // If we have external storage use it for the disk cache. Otherwise we use + // the cache dir + if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { + cacheLocation = new File( + Environment.getExternalStorageDirectory() + "/blaupload"); + } else { + cacheLocation = new File(getFilesDir() + "/blaupload"); + } + cacheLocation.mkdirs(); + + BitmapLruCache.Builder builder = new BitmapLruCache.Builder(this); + builder.setMemoryCacheEnabled(true).setMemoryCacheMaxSizeUsingHeapSize(); + builder.setDiskCacheEnabled(true).setDiskCacheLocation(cacheLocation); + + + mCache = builder.build(); + + Log.d(BlauploadApplication.class.toString(), cacheLocation.toString()); + } + + public BitmapLruCache getBitmapCache() { + return mCache; + } + + public static BlauploadApplication getApplication(Context context) { + return (BlauploadApplication) context.getApplicationContext(); + } + +} \ No newline at end of file diff --git a/app/src/main/java/uk/co/blatech/blaupload/HomeScreenFragment.java b/app/src/main/java/uk/co/blatech/blaupload/HomeScreenFragment.java index 6e6369b..ee51908 100644 --- a/app/src/main/java/uk/co/blatech/blaupload/HomeScreenFragment.java +++ b/app/src/main/java/uk/co/blatech/blaupload/HomeScreenFragment.java @@ -1,6 +1,7 @@ package uk.co.blatech.blaupload; import android.app.Activity; +import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.app.Fragment; @@ -40,6 +41,8 @@ public class HomeScreenFragment extends Fragment { private ArrayList thumbnails; private GridViewAdapter gridAdapter; private GridView gridView; + private ArrayList filenames; + private JSONArray json; /** * Returns a new instance of this fragment */ @@ -73,12 +76,17 @@ public class HomeScreenFragment extends Fragment { new GridViewAdapter(getActivity(), R.layout.grid_item, thumbnails); gridView.setAdapter(gridAdapter); - //Display a message when an item is clicked - //TODO: Make it display the full image + filenames = new ArrayList(); + //Open the full image in a pager when clicked gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { public void onItemClick(AdapterView parent, View v, int position, long id) { - Toast.makeText(getActivity(), "Clicked image #"+position, Toast.LENGTH_SHORT).show(); + + Toast.makeText(getActivity(), "Clicked image #"+position, Toast.LENGTH_SHORT).show(); + Intent mIntent = new Intent(getActivity(), ImagePager.class); + mIntent.putExtra("json", json.toString()); + mIntent.putExtra("position", position); + startActivity(mIntent); } @@ -90,7 +98,7 @@ public class HomeScreenFragment extends Fragment { super.onAttach(activity); //Start loading the JSON file list in a thread as soon as we start - new JSONLoader().execute("http://www.blaupload.co.uk/?format=json&last=9"); + new JSONLoader().execute("http://www.blaupload.co.uk/?format=json&last=6"); } @@ -125,8 +133,7 @@ public class HomeScreenFragment extends Fragment { @Subscribe public void onAsyncTaskResult(JSONLoaderResultEvent event) { - JSONArray json = event.getResult(); - ArrayList filenames = new ArrayList(); + json = event.getResult(); if (json != null) { @@ -146,7 +153,7 @@ public class HomeScreenFragment extends Fragment { //Load the thumbnail for each item on a thread int id = 0; for (String filename : filenames) { - new ImageLoader(getResources()).execute("http://www.lc8n.com/blathumbs/", filename, String.valueOf(id)); + new ImageLoader(getResources()).execute("http://www.lc8n.com/blathumbs/", filename+".png", String.valueOf(id)); id++; } diff --git a/app/src/main/java/uk/co/blatech/blaupload/ImagePager.java b/app/src/main/java/uk/co/blatech/blaupload/ImagePager.java new file mode 100644 index 0000000..0191c52 --- /dev/null +++ b/app/src/main/java/uk/co/blatech/blaupload/ImagePager.java @@ -0,0 +1,85 @@ +package uk.co.blatech.blaupload; + +import android.app.Activity; +import android.os.Bundle; +import android.support.v4.view.ViewPager; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; + +import com.squareup.otto.Subscribe; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; + +import uk.co.blatech.blaupload.R; +import uk.co.blatech.blaupload.data.ImageItem; +import uk.co.blatech.blaupload.ui.ImagePagerAdapter; +import uk.co.blatech.blaupload.util.EventBus; +import uk.co.blatech.blaupload.util.ImageLoader; +import uk.co.blatech.blaupload.util.ImageLoaderResultEvent; + +public class ImagePager extends Activity { + + + private ViewPager mViewPager; + private JSONArray json; + private ArrayList urls; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mViewPager = new ViewPager(this); + setContentView(mViewPager); + EventBus.getInstance().register(this); + urls = new ArrayList(); + String jsonText = getIntent().getStringExtra("json"); + int id = getIntent().getIntExtra("position", 0); + + try { + json = new JSONArray(jsonText); + } catch (JSONException e) { + //TODO: Error handling if we got something other than JSON + Log.e(ImagePager.class.toString(), "Failed to parse JSON"); + e.printStackTrace(); + } + + for (int i = 0; i < json.length(); i++) { + try { + JSONObject item = json.getJSONObject(i); + urls.add("http://www.blaupload.co.uk/"+item.getString("filename")); + } catch (JSONException e) { + e.printStackTrace(); + } + + } + + ImagePagerAdapter adapter = new ImagePagerAdapter(ImagePager.this, urls); + mViewPager.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.image_pager, 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); + } + + +} diff --git a/app/src/main/java/uk/co/blatech/blaupload/ui/DepthPageTransformer.java b/app/src/main/java/uk/co/blatech/blaupload/ui/DepthPageTransformer.java new file mode 100644 index 0000000..d2a5af3 --- /dev/null +++ b/app/src/main/java/uk/co/blatech/blaupload/ui/DepthPageTransformer.java @@ -0,0 +1,41 @@ +package uk.co.blatech.blaupload.ui; + +import android.support.v4.view.ViewPager; +import android.view.View; + +public class DepthPageTransformer implements ViewPager.PageTransformer { + private static final float MIN_SCALE = 0.75f; + + public void transformPage(View view, float position) { + int pageWidth = view.getWidth(); + + if (position < -1) { // [-Infinity,-1) + // This page is way off-screen to the left. + view.setAlpha(0); + + } else if (position <= 0) { // [-1,0] + // Use the default slide transition when moving to the left page + view.setAlpha(1); + view.setTranslationX(0); + view.setScaleX(1); + view.setScaleY(1); + + } else if (position <= 1) { // (0,1] + // Fade the page out. + view.setAlpha(1 - position); + + // Counteract the default slide transition + view.setTranslationX(pageWidth * -position); + + // Scale the page down (between MIN_SCALE and 1) + float scaleFactor = MIN_SCALE + + (1 - MIN_SCALE) * (1 - Math.abs(position)); + view.setScaleX(scaleFactor); + view.setScaleY(scaleFactor); + + } else { // (1,+Infinity] + // This page is way off-screen to the right. + view.setAlpha(0); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/uk/co/blatech/blaupload/ui/ImagePagerAdapter.java b/app/src/main/java/uk/co/blatech/blaupload/ui/ImagePagerAdapter.java new file mode 100644 index 0000000..4f5dba0 --- /dev/null +++ b/app/src/main/java/uk/co/blatech/blaupload/ui/ImagePagerAdapter.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2013 Chris Banes. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************/ +package uk.co.blatech.blaupload.ui; + +import android.content.Context; +import android.support.v4.view.PagerAdapter; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.widget.ImageView.ScaleType; + +import java.util.ArrayList; + +public class ImagePagerAdapter extends PagerAdapter { + + private final ArrayList mUrls; + + private final Context mContext; + + public ImagePagerAdapter(Context context, ArrayList urls) { + mUrls = urls; + mContext = context; + } + + @Override + public int getCount() { + return null != mUrls ? mUrls.size() : 0; + } + + @Override + public View instantiateItem(ViewGroup container, int position) { + NetworkCacheableImageView imageView = new NetworkCacheableImageView(mContext, null); + + String url = mUrls.get(position); + imageView.loadImage(url, true, null); + + imageView.setScaleType(ScaleType.FIT_CENTER); + container.addView(imageView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + + return imageView; + } + + @Override + public void destroyItem(ViewGroup container, int position, Object object) { + container.removeView((View) object); + } + + @Override + public boolean isViewFromObject(View view, Object object) { + return view == object; + } + +} diff --git a/app/src/main/java/uk/co/blatech/blaupload/ui/NetworkCacheableImageView.java b/app/src/main/java/uk/co/blatech/blaupload/ui/NetworkCacheableImageView.java new file mode 100644 index 0000000..043caae --- /dev/null +++ b/app/src/main/java/uk/co/blatech/blaupload/ui/NetworkCacheableImageView.java @@ -0,0 +1,271 @@ +/******************************************************************************* + * Copyright (c) 2013 Chris Banes. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************/ + +package uk.co.blatech.blaupload.ui; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Matrix; +import android.graphics.drawable.BitmapDrawable; +import android.opengl.GLES10; +import android.os.AsyncTask; +import android.os.Build; +import android.util.AttributeSet; +import android.util.Log; +import android.widget.ImageView; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.StatusLine; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.util.EntityUtils; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.ref.WeakReference; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.concurrent.RejectedExecutionException; + +import javax.microedition.khronos.opengles.GL10; + +import uk.co.blatech.blaupload.BlauploadApplication; +import uk.co.blatech.blaupload.R; +import uk.co.blatech.blaupload.data.ImageItem; +import uk.co.senab.bitmapcache.BitmapLruCache; +import uk.co.senab.bitmapcache.CacheableBitmapDrawable; +import uk.co.senab.bitmapcache.CacheableImageView; + +/** + * Simple extension of CacheableImageView which allows downloading of Images of the Internet. + * + * This code isn't production quality, but works well enough for this sample.s + * + * @author Chris Banes + */ +public class NetworkCacheableImageView extends CacheableImageView { + + public interface OnImageLoadedListener { + void onImageLoaded(CacheableBitmapDrawable result); + } + + /** + * This task simply fetches an Bitmap from the specified URL and wraps it in a wrapper. This + * implementation is NOT 'best practice' or production ready code. + */ + private static class ImageUrlAsyncTask + extends AsyncTask { + + private final BitmapLruCache mCache; + + private final WeakReference mImageViewRef; + private final OnImageLoadedListener mListener; + + private final BitmapFactory.Options mDecodeOpts; + + ImageUrlAsyncTask(ImageView imageView, BitmapLruCache cache, + BitmapFactory.Options decodeOpts, OnImageLoadedListener listener) { + mCache = cache; + mImageViewRef = new WeakReference(imageView); + mListener = listener; + mDecodeOpts = decodeOpts; + } + + @Override + protected CacheableBitmapDrawable doInBackground(String... params) { + + // Return early if the ImageView has disappeared. + if (null == mImageViewRef.get()) { + return null; + } + + final String url = params[0]; + + // Now we're not on the main thread we can check all caches + CacheableBitmapDrawable result = mCache.get(url); + + if (null == result) { + Log.d("ImageUrlAsyncTask", "Downloading: " + url); + +// // The bitmap isn't cached so download from the web +// HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); +// InputStream is = new BufferedInputStream(conn.getInputStream()); + Bitmap bmp = downloadImage(url); + // Add to cache + if (bmp != null) { + result = mCache.put(url, bmp); + } + } else { + Log.d("ImageUrlAsyncTask", "Got from Cache: " + url); + } + + return result; + + + } + + @Override + protected void onPostExecute(CacheableBitmapDrawable result) { + super.onPostExecute(result); + + ImageView iv = mImageViewRef.get(); + if (null != iv) { + iv.setImageDrawable(result); + } + + if (null != mListener) { + mListener.onImageLoaded(result); + } + } + + private Bitmap downloadImage(String url) { + + + DefaultHttpClient client = new DefaultHttpClient(); + HttpGet httpGet = new HttpGet(url); + Bitmap bmp = null; + + + int[] maxTextureSize = new int[1]; + maxTextureSize[0] = 4096; + GLES10.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, maxTextureSize, 0); + //TODO: Fix out of memory errors + try { + HttpResponse response = client.execute(httpGet); + StatusLine statusLine = response.getStatusLine(); + int statusCode = statusLine.getStatusCode(); + String[] parts = url.split("\\."); + String extension = parts[parts.length-1]; + //Create the Bitmap if the file exists + if (statusCode == 200 && isImageExtension(extension)) { + // If the thumbnail wasn't found, show a placeholder + HttpEntity entity = response.getEntity(); + byte[] bytes = EntityUtils.toByteArray(entity); + try { + bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); + } catch (Exception e) { + Log.e(NetworkCacheableImageView.class.toString(), "Failed decoding " + url); + e.printStackTrace(); + return bmp; + } + int bmpHeight = bmp.getHeight(); + int bmpWidth = bmp.getWidth(); + if (bmpWidth > maxTextureSize[0]) { + + float ratio = (float)maxTextureSize[0]/(float)bmpWidth; + Matrix matrix = new Matrix(); + bmpWidth = maxTextureSize[0]; + bmpHeight = Math.round(bmpHeight * ratio); + matrix.postScale(ratio, ratio); + bmp = Bitmap.createBitmap(bmp, 0, 0, bmpWidth, bmpHeight, matrix, false); + } else if (bmpHeight > maxTextureSize[0]) { + float ratio = (float)maxTextureSize[0]/(float)bmpHeight; + bmpHeight = maxTextureSize[0]; + bmpWidth = Math.round(bmpWidth * ratio); + Matrix matrix = new Matrix(); + matrix.postScale(ratio, ratio); + bmp = Bitmap.createBitmap(bmp, 0, 0, bmpWidth, bmpHeight, matrix, false); + } + } else { + //If the file doesn't exist, use the placeholder instead +// bmp = BitmapFactory.decodeResource(res, R.drawable.x); + return bmp; + } + + //TODO: Error handling (Not sure how we get here) + } catch (ClientProtocolException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + return bmp; + } + + private boolean isImageExtension(String extension) { + if (extension.equalsIgnoreCase("jpeg") || extension.equalsIgnoreCase("jpg") || + extension.equalsIgnoreCase("gif") || extension.equalsIgnoreCase("png")) { + return true; + } else { + return false; + } + } + } + + private final BitmapLruCache mCache; + + private ImageUrlAsyncTask mCurrentTask; + + public NetworkCacheableImageView(Context context, AttributeSet attrs) { + super(context, attrs); + mCache = BlauploadApplication.getApplication(context).getBitmapCache(); + } + + /** + * Loads the Bitmap. + * + * @param url - URL of image + * @param fullSize - Whether the image should be kept at the original size + * @return true if the bitmap was found in the cache + */ + public boolean loadImage(String url, final boolean fullSize, OnImageLoadedListener listener) { + // First check whether there's already a task running, if so cancel it + if (null != mCurrentTask) { + mCurrentTask.cancel(true); + } + + // Check to see if the memory cache already has the bitmap. We can + // safely do + // this on the main thread. + BitmapDrawable wrapper = mCache.getFromMemoryCache(url); + + if (null != wrapper) { + // The cache has it, so just display it + setImageDrawable(wrapper); + return true; + } else { + // Memory Cache doesn't have the URL, do threaded request... + setImageDrawable(null); + + BitmapFactory.Options decodeOpts = null; + + if (!fullSize) { + //decodeOpts = new BitmapFactory.Options(); + //decodeOpts.inSampleSize = 2; + } + + mCurrentTask = new ImageUrlAsyncTask(this, mCache, decodeOpts, listener); + + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + mCurrentTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url); + } else { + mCurrentTask.execute(url); + } + } catch (RejectedExecutionException e) { + // This shouldn't happen, but might. + } + + return false; + } + } + +} diff --git a/app/src/main/java/uk/co/blatech/blaupload/ui/ZoomViewPager.java b/app/src/main/java/uk/co/blatech/blaupload/ui/ZoomViewPager.java new file mode 100644 index 0000000..e0b837e --- /dev/null +++ b/app/src/main/java/uk/co/blatech/blaupload/ui/ZoomViewPager.java @@ -0,0 +1,75 @@ +package uk.co.blatech.blaupload.ui; + +import android.content.Context; +import android.support.v4.view.ViewPager; +import android.util.AttributeSet; +import android.view.MotionEvent; + +/** + * Found at http://stackoverflow.com/questions/7814017/is-it-possible-to-disable-scrolling-on-a-viewpager. + * Convenient way to temporarily disable ViewPager navigation while interacting with ImageView. + * + * Julia Zudikova + */ + +/** + * Hacky fix for Issue #4 and + * http://code.google.com/p/android/issues/detail?id=18990 + *

+ * ScaleGestureDetector seems to mess up the touch events, which means that + * ViewGroups which make use of onInterceptTouchEvent throw a lot of + * IllegalArgumentException: pointerIndex out of range. + *

+ * There's not much I can do in my code for now, but we can mask the result by + * just catching the problem and ignoring it. + * + * @author Chris Banes + */ +public class ZoomViewPager extends ViewPager { + + private boolean isLocked; + + public ZoomViewPager(Context context) { + super(context); + isLocked = false; + } + + public ZoomViewPager(Context context, AttributeSet attrs) { + super(context, attrs); + isLocked = false; + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + if (!isLocked) { + try { + return super.onInterceptTouchEvent(ev); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + return false; + } + } + return false; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (!isLocked) { + return super.onTouchEvent(event); + } + return false; + } + + public void toggleLock() { + isLocked = !isLocked; + } + + public void setLocked(boolean isLocked) { + this.isLocked = isLocked; + } + + public boolean isLocked() { + return isLocked; + } + +} \ No newline at end of file diff --git a/app/src/main/java/uk/co/blatech/blaupload/util/ImageLoader.java b/app/src/main/java/uk/co/blatech/blaupload/util/ImageLoader.java index 9af9a26..4a2dbc5 100644 --- a/app/src/main/java/uk/co/blatech/blaupload/util/ImageLoader.java +++ b/app/src/main/java/uk/co/blatech/blaupload/util/ImageLoader.java @@ -1,9 +1,14 @@ package uk.co.blatech.blaupload.util; +import android.annotation.TargetApi; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.Matrix; +import android.opengl.GLES10; import android.os.AsyncTask; +import android.os.Build; +import android.util.Log; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; @@ -15,6 +20,8 @@ import org.apache.http.util.EntityUtils; import java.io.IOException; +import javax.microedition.khronos.opengles.GL10; + import uk.co.blatech.blaupload.R; import uk.co.blatech.blaupload.data.ImageItem; @@ -50,9 +57,12 @@ public class ImageLoader extends AsyncTask { String host = args[0]; String filename = args[1]; int id = Integer.parseInt(args[2]); + int[] maxTextureSize = new int[1]; + maxTextureSize[0] = 4096; + GLES10.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, maxTextureSize, 0); //Add an extra .png on the end to match the current thumbnail filenames - String url = host + filename + ".png"; + String url = host + filename; DefaultHttpClient client = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(url); @@ -62,13 +72,40 @@ public class ImageLoader extends AsyncTask { HttpResponse response = client.execute(httpGet); StatusLine statusLine = response.getStatusLine(); int statusCode = statusLine.getStatusCode(); - + String[] parts = filename.split("\\."); + String extension = parts[parts.length-1]; //Create the Bitmap if the file exists - if (statusCode == 200) { + if (statusCode == 200 && isImageExtension(extension)) { // If the thumbnail wasn't found, show a placeholder HttpEntity entity = response.getEntity(); byte[] bytes = EntityUtils.toByteArray(entity); - bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); + try { + bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); + } catch (Exception e) { + Log.e(ImageLoader.class.toString(), "Failed decoding " + filename); + e.printStackTrace(); + bmp = BitmapFactory.decodeResource(res, R.drawable.x); + ImageItem image = new ImageItem(id, bmp, filename); + return image; + } + int bmpHeight = bmp.getHeight(); + int bmpWidth = bmp.getWidth(); + if (bmpWidth > maxTextureSize[0]) { + + float ratio = (float)maxTextureSize[0]/(float)bmpWidth; + Matrix matrix = new Matrix(); + bmpWidth = maxTextureSize[0]; + bmpHeight = Math.round(bmpHeight * ratio); + matrix.postScale(ratio, ratio); + bmp = Bitmap.createBitmap(bmp, 0, 0, bmpWidth, bmpHeight, matrix, false); + } else if (bmpHeight > maxTextureSize[0]) { + float ratio = (float)maxTextureSize[0]/(float)bmpHeight; + bmpHeight = maxTextureSize[0]; + bmpWidth = Math.round(bmpWidth * ratio); + Matrix matrix = new Matrix(); + matrix.postScale(ratio, ratio); + bmp = Bitmap.createBitmap(bmp, 0, 0, bmpWidth, bmpHeight, matrix, false); + } } else { //If the file doesn't exist, use the placeholder instead bmp = BitmapFactory.decodeResource(res, R.drawable.x); @@ -92,4 +129,13 @@ public class ImageLoader extends AsyncTask { } + private boolean isImageExtension(String extension) { + if (extension.equalsIgnoreCase("jpeg") || extension.equalsIgnoreCase("jpg") || + extension.equalsIgnoreCase("gif") || extension.equalsIgnoreCase("png")) { + return true; + } else { + return false; + } + } + } diff --git a/app/src/main/res/layout/activity_image_pager.xml b/app/src/main/res/layout/activity_image_pager.xml new file mode 100644 index 0000000..74181fa --- /dev/null +++ b/app/src/main/res/layout/activity_image_pager.xml @@ -0,0 +1,16 @@ + + + + + diff --git a/app/src/main/res/layout/activity_image_viewer.xml b/app/src/main/res/layout/activity_image_viewer.xml new file mode 100644 index 0000000..9eef971 --- /dev/null +++ b/app/src/main/res/layout/activity_image_viewer.xml @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_image_viewer.xml b/app/src/main/res/layout/fragment_image_viewer.xml new file mode 100644 index 0000000..d9f75fa --- /dev/null +++ b/app/src/main/res/layout/fragment_image_viewer.xml @@ -0,0 +1,13 @@ + + + + diff --git a/app/src/main/res/menu/image_pager.xml b/app/src/main/res/menu/image_pager.xml new file mode 100644 index 0000000..67ae247 --- /dev/null +++ b/app/src/main/res/menu/image_pager.xml @@ -0,0 +1,8 @@ +

+ + diff --git a/app/src/main/res/menu/image_viewer.xml b/app/src/main/res/menu/image_viewer.xml new file mode 100644 index 0000000..bed19e0 --- /dev/null +++ b/app/src/main/res/menu/image_viewer.xml @@ -0,0 +1,8 @@ + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 25d7732..ba06821 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -10,5 +10,8 @@ Example action Settings Hello blank fragment + ImageViewer + Hello world! + ImagePager -- cgit v1.2.3