constructor = mViewHolderClass.getConstructor(View.class);
return constructor.newInstance(view);
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 000000000..e8cf5b930
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,19 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+org.gradle.jvmargs=-Xmx1536m
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index e49aa46d9..35b960afd 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Tue Aug 02 23:08:04 SGT 2016
+#Tue Sep 27 18:02:33 SGT 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.1-all.zip
diff --git a/library/build.gradle b/library/build.gradle
index 8ef4d199a..a67a94177 100644
--- a/library/build.gradle
+++ b/library/build.gradle
@@ -22,8 +22,6 @@ android {
dependencies {
compile project(':database')
compile project(':auth')
-
- androidTestCompile 'junit:junit:4.12'
}
/**
@@ -61,7 +59,7 @@ def bintrayUploadTasks() {
*/
def testTasks() {
return project.ext.submodules.collect { name ->
- ":${name}:test"
+ ":${name}:testDebugUnitTest"
}.toArray()
}
diff --git a/settings.gradle b/settings.gradle
index 99385987d..81b4dd520 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1 +1 @@
-include ':app', ':common', ':library', ':database', ':auth'
+include ':app', ':common', ':library', ':database', ':auth', ':storage'
diff --git a/storage/.gitignore b/storage/.gitignore
new file mode 100644
index 000000000..796b96d1c
--- /dev/null
+++ b/storage/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/storage/README.md b/storage/README.md
new file mode 100644
index 000000000..dc702fe38
--- /dev/null
+++ b/storage/README.md
@@ -0,0 +1,63 @@
+# FirebaseUI for Android — Storage
+
+## Using FirebaseUI to download and display images
+
+[Firebase Storage][firebase-storage] provides secure file uploads and downloads for your Firebase apps,
+regardless of network quality. You can use it to store images, audio, video, or other
+user-generated content. Firebase Storage is backed by Google Cloud Storage, a powerful, simple,
+and cost-effective object storage service.
+
+FirebaseUI provides bindings to download an image file stored in Firebase Storage
+from a [`StorageReference`][storage-reference] and display it using the popular
+[Glide][glide] library. This technique allows you to get all of Glide's performance
+benefits while leveraging Firebase Storage's authenticated storage capabilities.
+
+To load an image from a `StorageReference`, simply use the `FirebaseImageLoader` class:
+
+```java
+ // Reference to an image file in Firebase Storage
+ StorageReference storageReference = ...;
+
+ // ImageView in your Activity
+ ImageView imageView = ...;
+
+ // Load the image using Glide
+ Glide.with(this /* context */)
+ .using(new FirebaseImageLoader())
+ .load(storageReference)
+ .into(imageView);
+```
+
+Images displayed using `FirebaseImageLoader` are cached by their path in Firebase Storage, so
+repeated loads will be fast and conserve bandwidth. For more information on caching in Glide,
+see [this guide][glide-caching].
+
+## Known Issues
+
+There is a bug in `com.google.firebase:firebase-storage:9.6.0` and earlier that results in
+excessive logging when downloading images. You may see messages in your logs like this:
+
+```
+W/StorageTask: unable to change internal state to: INTERNAL_STATE_IN_PROGRESS isUser: false from state:INTERNAL_STATE_SUCCESS
+```
+
+In production this could slow your app down if you are downloading many images. The suggested
+workaround is to disable logging in production by adding the following lines to your
+ProGuard configuration (`proguard-rules.pro`):
+
+```
+-assumenosideeffects class android.util.Log {
+ public static int w(...);
+ public static int d(...);
+ public static int v(...);
+}
+```
+
+This will disable calls to `Log.w()`, `Log.d()`, and `Log.v()` but preserve log calls at the
+`INFO` and `ERROR` levels. Note that this will only be effective when using
+`proguard-android-optimize.txt` as the default ProGuard file in `build.gradle`.
+
+[firebase-storage]: https://firebase.google.com/docs/storage/
+[glide]: https://github.com/bumptech/glide
+[storage-reference]: https://firebase.google.com/docs/reference/android/com/google/firebase/storage/StorageReference
+[glide-caching]: https://github.com/bumptech/glide/wiki/Caching-and-Cache-Invalidation
\ No newline at end of file
diff --git a/storage/build.gradle b/storage/build.gradle
new file mode 100644
index 000000000..d8ee288d9
--- /dev/null
+++ b/storage/build.gradle
@@ -0,0 +1,28 @@
+apply plugin: 'com.android.library'
+
+android {
+ compileSdkVersion project.ext.compileSdk
+ buildToolsVersion "${project.ext.buildtools}"
+
+ defaultConfig {
+ minSdkVersion 11
+ targetSdkVersion project.ext.targetSdk
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ compile "com.android.support:appcompat-v7:${project.ext.support_library_version}"
+ compile "com.android.support:palette-v7:${project.ext.support_library_version}"
+
+ compile 'com.github.bumptech.glide:glide:3.7.0'
+
+ compile "com.google.firebase:firebase-storage:${project.ext.firebase_version}"
+}
diff --git a/storage/proguard-rules.pro b/storage/proguard-rules.pro
new file mode 100644
index 000000000..a5afa4992
--- /dev/null
+++ b/storage/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /usr/local/google/home/samstern/android-sdk-linux/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/storage/src/main/AndroidManifest.xml b/storage/src/main/AndroidManifest.xml
new file mode 100644
index 000000000..53c6a6e5c
--- /dev/null
+++ b/storage/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+
+
+
diff --git a/storage/src/main/java/com/firebase/ui/storage/images/FirebaseImageLoader.java b/storage/src/main/java/com/firebase/ui/storage/images/FirebaseImageLoader.java
new file mode 100644
index 000000000..f5392d369
--- /dev/null
+++ b/storage/src/main/java/com/firebase/ui/storage/images/FirebaseImageLoader.java
@@ -0,0 +1,82 @@
+package com.firebase.ui.storage.images;
+
+import android.util.Log;
+
+import com.bumptech.glide.Priority;
+import com.bumptech.glide.load.data.DataFetcher;
+import com.bumptech.glide.load.model.stream.StreamModelLoader;
+import com.google.android.gms.tasks.Tasks;
+import com.google.firebase.storage.StorageReference;
+import com.google.firebase.storage.StreamDownloadTask;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * ModelLoader implementation to download images from FirebaseStorage with Glide.
+ *
+ * Sample Usage:
+ *
+ * StorageReference ref = FirebaseStorage.getInstance().getReference().child("myimage");
+ * ImageView iv = (ImageView) findViewById(R.id.my_image_view);
+ *
+ * Glide.with(this)
+ * .using(new FirebaseImageLoader())
+ * .load(ref)
+ * .into(iv);
+ *
+ */
+public class FirebaseImageLoader implements StreamModelLoader {
+
+ private static final String TAG = "FirebaseImageLoader";
+
+ @Override
+ public DataFetcher getResourceFetcher(StorageReference model, int width, int height) {
+ return new FirebaseStorageFetcher(model);
+ }
+
+ private class FirebaseStorageFetcher implements DataFetcher {
+
+ private StorageReference mRef;
+ private StreamDownloadTask mStreamTask;
+ private InputStream mInputStream;
+
+ FirebaseStorageFetcher(StorageReference ref) {
+ mRef = ref;
+ }
+
+ @Override
+ public InputStream loadData(Priority priority) throws Exception {
+ mStreamTask = mRef.getStream();
+ mInputStream = Tasks.await(mStreamTask).getStream();
+
+ return mInputStream;
+ }
+
+ @Override
+ public void cleanup() {
+ // Close stream if possible
+ if (mInputStream != null) {
+ try {
+ mInputStream.close();
+ mInputStream = null;
+ } catch (IOException e) {
+ Log.w(TAG, "Could not close stream", e);
+ }
+ }
+ }
+
+ @Override
+ public String getId() {
+ return mRef.getPath();
+ }
+
+ @Override
+ public void cancel() {
+ // Cancel task if possible
+ if (mStreamTask != null && mStreamTask.isInProgress()) {
+ mStreamTask.cancel();
+ }
+ }
+ }
+}