Skip to content

Commit

Permalink
Version 0.6.0, FirebaseUI Storage (#324)
Browse files Browse the repository at this point in the history
  • Loading branch information
samtstern committed Sep 24, 2016
1 parent 11bc4ce commit 3ee51f2
Show file tree
Hide file tree
Showing 17 changed files with 467 additions and 16 deletions.
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,16 @@ libraries.
```groovy
dependencies {
// Single target that includes all FirebaseUI libraries
compile 'com.firebaseui:firebase-ui:0.5.3'
compile 'com.firebaseui:firebase-ui:0.6.0'
// FirebaseUI Database only
compile 'com.firebaseui:firebase-ui-database:0.5.3'
compile 'com.firebaseui:firebase-ui-database:0.6.0'
// FirebaseUI Auth only
compile 'com.firebaseui:firebase-ui-auth:0.5.3'
compile 'com.firebaseui:firebase-ui-auth:0.6.0'
// FirebaseUI Storage only
compile 'com.firebasui:firebase-ui-storage:0.6.0'
}
```

Expand All @@ -50,6 +53,9 @@ firebase-ui-auth
firebase-ui-database
|--- com.google.firebase:firebase-database
firebase-ui-storage
|--- com.google.firebase:firebase-storage
```

Each version of FirebaseUI has dependency on a fixed version of these libraries, defined as the variable `firebase_version`
Expand All @@ -61,6 +67,7 @@ For convenience, here are some examples:

| FirebaseUI Version | Firebase/Play Services Version |
|--------------------|--------------------------------|
| 0.6.0 | 9.6.0 |
| 0.5.3 | 9.4.0 |
| 0.4.4 | 9.4.0 |
| 0.4.3 | 9.2.1 |
Expand All @@ -72,6 +79,7 @@ For convenience, here are some examples:

* [firebase-ui-database](database/README.md)
* [firebase-ui-auth](auth/README.md)
* [firebase-ui-storage](storage/README.md)

## Sample App

Expand Down
11 changes: 9 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@ android {

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'

// For the purposes of the sample, allow testing of a proguarded release build
// using the debug key
signingConfig signingConfigs.debug
}
}

Expand All @@ -32,16 +36,19 @@ dependencies {

compile project(path: ':auth')
compile project(path: ':database')
compile project(path: ':storage')

compile "com.google.firebase:firebase-database:${project.ext.firebase_version}"
compile "com.google.firebase:firebase-auth:${project.ext.firebase_version}"
compile "com.google.firebase:firebase-storage:${project.ext.firebase_version}"
compile "com.google.android.gms:play-services-auth:${project.ext.firebase_version}"

// The following dependencies are not required to use the Firebase UI library.
// They are used to make some aspects of the demo app implementation simpler for
// demonstrative purposes, and you may find them useful in your own apps; YMMV.
compile 'com.jakewharton:butterknife:8.0.1'
compile 'com.github.bumptech.glide:glide:3.7.0'
compile 'pub.devrel:easypermissions:0.2.0'
apt 'com.jakewharton:butterknife-compiler:8.0.1'
}

Expand Down
8 changes: 8 additions & 0 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,11 @@
# https://firebase-dot-devsite.googleplex.com/docs/auth/android/start/#proguard
-keepattributes Signature
-keepattributes *Annotation*

# See:
# storage/README.md
-assumenosideeffects class android.util.Log {
public static *** w(...);
public static *** d(...);
public static *** v(...);
}
4 changes: 2 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
package="com.firebase.uidemo">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">

<activity android:name=".ChooserActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
Expand All @@ -27,10 +27,10 @@
<activity
android:name=".auth.AuthUiActivity"
android:label="@string/name_auth_ui" />

<activity
android:name=".auth.SignedInActivity"
android:label="@string/name_auth_ui" />
<activity android:name=".storage.ImageActivity"></activity>
</application>

</manifest>
8 changes: 6 additions & 2 deletions app/src/main/java/com/firebase/uidemo/ChooserActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

import com.firebase.uidemo.auth.AuthUiActivity;
import com.firebase.uidemo.database.ChatActivity;
import com.firebase.uidemo.storage.ImageActivity;

import butterknife.BindView;
import butterknife.ButterKnife;
Expand All @@ -37,16 +38,19 @@ public class ChooserActivity extends AppCompatActivity {
private static final Class[] CLASSES = new Class[]{
ChatActivity.class,
AuthUiActivity.class,
ImageActivity.class,
};

private static final int[] DESCRIPTION_NAMES = new int[] {
R.string.name_chat,
R.string.name_auth_ui
R.string.name_auth_ui,
R.string.name_image
};

private static final int[] DESCRIPTION_IDS = new int[] {
R.string.desc_chat,
R.string.desc_auth_ui
R.string.desc_auth_ui,
R.string.desc_image
};

@BindView(R.id.list_view)
Expand Down
167 changes: 167 additions & 0 deletions app/src/main/java/com/firebase/uidemo/storage/ImageActivity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
package com.firebase.uidemo.storage;

import android.Manifest;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import com.bumptech.glide.Glide;
import com.firebase.ui.storage.images.FirebaseImageLoader;
import com.firebase.uidemo.R;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageReference;
import com.google.firebase.storage.UploadTask;

import java.util.UUID;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import pub.devrel.easypermissions.AfterPermissionGranted;
import pub.devrel.easypermissions.EasyPermissions;

public class ImageActivity extends AppCompatActivity {

private static final String TAG = "ImageDemo";
private static final int RC_CHOOSE_PHOTO = 101;
private static final int RC_IMAGE_PERMS = 102;

private StorageReference mImageRef;

@BindView(R.id.button_choose_photo)
Button mUploadButton;

@BindView(R.id.button_download_direct)
Button mDownloadDirectButton;

@BindView(R.id.first_image)
ImageView mImageView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image);
ButterKnife.bind(this);

// By default, Firebase Storage files require authentication to read or write.
// For this sample to function correctly, enable Anonymous Auth in the Firebase console:
// https://console.firebase.google.com/project/_/authentication/providers
FirebaseAuth.getInstance().signInAnonymously()
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
Log.d(TAG, "signInAnonymously:" + task.isSuccessful());
if (!task.isSuccessful()) {
Log.w(TAG, "signInAnonymously", task.getException());
Log.w(TAG, getString(R.string.anonymous_auth_failed_msg));

Toast.makeText(ImageActivity.this,
getString(R.string.anonymous_auth_failed_toast),
Toast.LENGTH_SHORT).show();
}
}
});
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);

if (requestCode == RC_CHOOSE_PHOTO) {
if (resultCode == RESULT_OK) {
Uri selectedImage = data.getData();
uploadPhoto(selectedImage);
} else {
Toast.makeText(this, "No image chosen", Toast.LENGTH_SHORT).show();
}
}
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}

@OnClick(R.id.button_choose_photo)
@AfterPermissionGranted(RC_IMAGE_PERMS)
protected void choosePhoto() {
String perm = Manifest.permission.READ_EXTERNAL_STORAGE;
if (!EasyPermissions.hasPermissions(this, perm)) {
EasyPermissions.requestPermissions(this, getString(R.string.rational_image_perm),
RC_IMAGE_PERMS, perm);
return;
}

Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, RC_CHOOSE_PHOTO);
}

protected void uploadPhoto(Uri uri) {
// Reset UI
hideDownloadUI();
Toast.makeText(this, "Uploading...", Toast.LENGTH_SHORT).show();

// Upload to Firebase Storage
String uuid = UUID.randomUUID().toString();
mImageRef = FirebaseStorage.getInstance().getReference(uuid);
mImageRef.putFile(uri)
.addOnSuccessListener(this, new OnSuccessListener<UploadTask.TaskSnapshot>() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Log.d(TAG, "uploadPhoto:onSuccess:" +
taskSnapshot.getMetadata().getReference().getPath());
Toast.makeText(ImageActivity.this, "Image uploaded",
Toast.LENGTH_SHORT).show();

showDownloadUI();
}
})
.addOnFailureListener(this, new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.w(TAG, "uploadPhoto:onError", e);
Toast.makeText(ImageActivity.this, "Upload failed",
Toast.LENGTH_SHORT).show();
}
});
}

@OnClick(R.id.button_download_direct)
protected void downloadDirect() {
// Download directly from StorageReference using Glide
Glide.with(this)
.using(new FirebaseImageLoader())
.load(mImageRef)
.centerCrop()
.crossFade()
.into(mImageView);
}

private void hideDownloadUI() {
mDownloadDirectButton.setEnabled(false);

mImageView.setImageResource(0);
mImageView.setVisibility(View.INVISIBLE);
}

private void showDownloadUI() {
mDownloadDirectButton.setEnabled(true);

mImageView.setVisibility(View.VISIBLE);
}
}
56 changes: 56 additions & 0 deletions app/src/main/res/layout/activity_image.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.firebase.uidemo.storage.ImageActivity">

<TextView
style="@style/TextAppearance.AppCompat.Medium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Upload" />

<Button
android:id="@+id/button_choose_photo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Choose Image" />

<TextView
style="@style/TextAppearance.AppCompat.Medium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Download" />

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">

<Button
android:id="@+id/button_download_direct"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:enabled="false"
android:text="Download" />

</LinearLayout>

<ImageView
android:id="@+id/first_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="#E6E6E6"
android:visibility="invisible"
tools:visibility="visible" />

</LinearLayout>
8 changes: 7 additions & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@

<string name="name_chat">ChatActivity</string>
<string name="name_auth_ui">Auth UI demo</string>
<string name="name_image">Storage Image Demo</string>

<string name="desc_chat">Demonstrates using a FirebaseRecyclerAdapter to load data from Firebase Database into a RecyclerView for a basic chat app.</string>
<string name="desc_auth_ui">Demonstrates the Firebase Auth UI flow, with customization options.</string>
<string name="desc_image">Demonstrates displaying an image from Firebase Storage using Glide.</string>

<!-- strings for Auth UI demo activities -->
<eat-comment/>
<eat-comment />
<string name="launch_title">FirebaseUI Auth Demo</string>
<string name="sign_in">Start</string>
<string name="green_theme">Green Theme</string>
Expand Down Expand Up @@ -42,4 +44,8 @@
<string name="configuration_required">Configuration is required - see README.md</string>
<string name="other_options_header">Other Options:</string>
<string name="enable_smartlock">Enable SmartLock for Passwords</string>
<string name="rational_image_perm">This sample will read an image from local storage to upload to Firebase Storage.</string>

<string name="anonymous_auth_failed_toast">Authentication failed, uploads and downloads will not work.</string>
<string name="anonymous_auth_failed_msg">Anonymous authentication failed. Make sure your device is online and that Anonymous Auth is configured in your Firebase project(https://console.firebase.google.com/project/_/authentication/providers)</string>
</resources>
Loading

0 comments on commit 3ee51f2

Please sign in to comment.