diff options
20 files changed, 749 insertions, 16 deletions
diff --git a/.idea/libraries/Android_BitmapCache_2_3.xml b/.idea/libraries/Android_BitmapCache_2_3.xml new file mode 100644 index 0000000..34c06f6 --- /dev/null +++ b/.idea/libraries/Android_BitmapCache_2_3.xml @@ -0,0 +1,9 @@ +<component name="libraryTable"> + <library name="Android-BitmapCache-2.3"> + <CLASSES> + <root url="jar://$PROJECT_DIR$/app/libs/Android-BitmapCache-2.3.jar!/" /> + </CLASSES> + <JAVADOC /> + <SOURCES /> + </library> +</component>
\ No newline at end of file diff --git a/.idea/libraries/disklrucache_2_0_2.xml b/.idea/libraries/disklrucache_2_0_2.xml new file mode 100644 index 0000000..45145e6 --- /dev/null +++ b/.idea/libraries/disklrucache_2_0_2.xml @@ -0,0 +1,11 @@ +<component name="libraryTable"> + <library name="disklrucache-2.0.2"> + <CLASSES> + <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.jakewharton/disklrucache/2.0.2/93b399470e72c0bc8cb52379943b63c9aa586cd8/disklrucache-2.0.2.jar!/" /> + </CLASSES> + <JAVADOC /> + <SOURCES> + <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.jakewharton/disklrucache/2.0.2/a8b600c9a1d9f75cdc45bb1b24b4731845a7658b/disklrucache-2.0.2-sources.jar!/" /> + </SOURCES> + </library> +</component>
\ No newline at end of file diff --git a/app/app.iml b/app/app.iml index ad43377..1556047 100644 --- a/app/app.iml +++ b/app/app.iml @@ -59,11 +59,13 @@ <excludeFolder url="file://$MODULE_DIR$/build/intermediates" /> <excludeFolder url="file://$MODULE_DIR$/build/outputs" /> </content> - <orderEntry type="jdk" jdkName="Android API 19 Platform" jdkType="Android SDK" /> + <orderEntry type="jdk" jdkName="Android API 17 Platform" jdkType="Android SDK" /> <orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="library" exported="" name="library-1.2.3" level="project" /> <orderEntry type="library" exported="" name="support-v4-19.1.0" level="project" /> + <orderEntry type="library" exported="" name="disklrucache-2.0.2" level="project" /> <orderEntry type="library" exported="" name="otto-1.3.5" level="project" /> + <orderEntry type="library" exported="" name="Android-BitmapCache-2.3" level="project" /> </component> </module> diff --git a/app/build.gradle b/app/build.gradle index cf01a63..d099f61 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.application' android { compileSdkVersion 19 - buildToolsVersion "20.0.0" + buildToolsVersion '20.0.0' defaultConfig { applicationId "uk.co.blatech.blaupload" @@ -25,5 +25,6 @@ dependencies { compile 'com.android.support:support-v4:19.+' compile 'com.squareup:otto:1.3.5' compile 'com.github.chrisbanes.photoview:library:1.2.3' - + compile 'com.jakewharton:disklrucache:2.0.2' + compile files('libs/Android-BitmapCache-2.3.jar') } 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 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="uk.co.blatech.blaupload" > - <uses-permission android:name="android.permission.INTERNET"/> + + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <application + android:name=".BlauploadApplication" android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" @@ -14,11 +17,22 @@ <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> + <action android:name="android.intent.action.SEND_MULTIPLE" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:mimeType="image/*" /> </intent-filter> </activity> + <activity + android:name=".ImageViewer" + android:label="@string/title_activity_image_viewer" > + </activity> + <activity + android:name=".ImagePager" + android:label="@string/title_activity_image_pager" > + </activity> </application> </manifest> 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<ImageItem> thumbnails; private GridViewAdapter gridAdapter; private GridView gridView; + private ArrayList<String> 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<String>(); + //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<String> filenames = new ArrayList<String>(); + 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<String> urls; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mViewPager = new ViewPager(this); + setContentView(mViewPager); + EventBus.getInstance().register(this); + urls = new ArrayList<String>(); + 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<String> mUrls; + + private final Context mContext; + + public ImagePagerAdapter(Context context, ArrayList<String> 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<String, Void, CacheableBitmapDrawable> { + + private final BitmapLruCache mCache; + + private final WeakReference<ImageView> 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>(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 + * <p/> + * 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. + * <p/> + * 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, Void, ImageItem> { 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<String, Void, ImageItem> { 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<String, Void, ImageItem> { } + 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/java/uk/co/blatech/blaupload/util/JSONLoader.java b/app/src/main/java/uk/co/blatech/blaupload/util/JSONLoader.java index 028202a..ffb9601 100644 --- a/app/src/main/java/uk/co/blatech/blaupload/util/JSONLoader.java +++ b/app/src/main/java/uk/co/blatech/blaupload/util/JSONLoader.java @@ -59,7 +59,7 @@ public class JSONLoader extends AsyncTask<String, Void, JSONArray> { DefaultHttpClient client = new DefaultHttpClient(); CookieStore cookieStore = new BasicCookieStore(); //TODO: Don't hard code the cookie. - BasicClientCookie cookie = new BasicClientCookie("password", "PASSWORDHASHHERE"); + BasicClientCookie cookie = new BasicClientCookie("password", "577f7781b7079fd9c0e67ef7e301617cf6eb317311ce8cd0b4b6b2652ffd14d5"); cookie.setDomain(".blaupload.co.uk"); cookie.setPath("/"); cookieStore.addCookie(cookie); 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 @@ +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:paddingLeft="@dimen/activity_horizontal_margin" + android:paddingRight="@dimen/activity_horizontal_margin" + android:paddingTop="@dimen/activity_vertical_margin" + android:paddingBottom="@dimen/activity_vertical_margin" + tools:context="uk.co.blatech.blaupload.ImagePager"> + + <TextView + android:text="@string/hello_world" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + +</RelativeLayout> 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 @@ +<uk.co.blatech.blaupload.ui.ZoomViewPager + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/pager" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context="uk.co.blatech.blaupload.ImageViewer"/>
\ 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 @@ +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context="uk.co.blatech.blaupload.ImageViewer$PlaceholderFragment"> + + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/imageView" + android:layout_centerVertical="true" + android:layout_centerHorizontal="true" /> +</RelativeLayout> 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 @@ +<menu xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + tools:context="uk.co.blatech.blaupload.ImagePager" > + <item android:id="@+id/action_settings" + android:title="@string/action_settings" + android:orderInCategory="100" + android:showAsAction="never" /> +</menu> 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 @@ +<menu xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + tools:context="uk.co.blatech.blaupload.ImageViewer" > + <item android:id="@+id/action_settings" + android:title="@string/action_settings" + android:orderInCategory="100" + android:showAsAction="never" /> +</menu> 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 @@ <string name="action_example">Example action</string> <string name="action_settings">Settings</string> <string name="hello_blank_fragment">Hello blank fragment</string> + <string name="title_activity_image_viewer">ImageViewer</string> + <string name="hello_world">Hello world!</string> + <string name="title_activity_image_pager">ImagePager</string> </resources> |