Skip to content

Commit 3ee51f2

Browse files
authored
Version 0.6.0, FirebaseUI Storage (#324)
1 parent 11bc4ce commit 3ee51f2

File tree

17 files changed

+467
-16
lines changed

17 files changed

+467
-16
lines changed

README.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,16 @@ libraries.
2828
```groovy
2929
dependencies {
3030
// Single target that includes all FirebaseUI libraries
31-
compile 'com.firebaseui:firebase-ui:0.5.3'
31+
compile 'com.firebaseui:firebase-ui:0.6.0'
3232
3333
// FirebaseUI Database only
34-
compile 'com.firebaseui:firebase-ui-database:0.5.3'
34+
compile 'com.firebaseui:firebase-ui-database:0.6.0'
3535
3636
// FirebaseUI Auth only
37-
compile 'com.firebaseui:firebase-ui-auth:0.5.3'
37+
compile 'com.firebaseui:firebase-ui-auth:0.6.0'
38+
39+
// FirebaseUI Storage only
40+
compile 'com.firebasui:firebase-ui-storage:0.6.0'
3841
}
3942
```
4043

@@ -50,6 +53,9 @@ firebase-ui-auth
5053
5154
firebase-ui-database
5255
|--- com.google.firebase:firebase-database
56+
57+
firebase-ui-storage
58+
|--- com.google.firebase:firebase-storage
5359
```
5460

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

6268
| FirebaseUI Version | Firebase/Play Services Version |
6369
|--------------------|--------------------------------|
70+
| 0.6.0 | 9.6.0 |
6471
| 0.5.3 | 9.4.0 |
6572
| 0.4.4 | 9.4.0 |
6673
| 0.4.3 | 9.2.1 |
@@ -72,6 +79,7 @@ For convenience, here are some examples:
7279

7380
* [firebase-ui-database](database/README.md)
7481
* [firebase-ui-auth](auth/README.md)
82+
* [firebase-ui-storage](storage/README.md)
7583

7684
## Sample App
7785

app/build.gradle

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,12 @@ android {
1616

1717
buildTypes {
1818
release {
19-
minifyEnabled false
20-
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
19+
minifyEnabled true
20+
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
21+
22+
// For the purposes of the sample, allow testing of a proguarded release build
23+
// using the debug key
24+
signingConfig signingConfigs.debug
2125
}
2226
}
2327

@@ -32,16 +36,19 @@ dependencies {
3236

3337
compile project(path: ':auth')
3438
compile project(path: ':database')
39+
compile project(path: ':storage')
3540

3641
compile "com.google.firebase:firebase-database:${project.ext.firebase_version}"
3742
compile "com.google.firebase:firebase-auth:${project.ext.firebase_version}"
43+
compile "com.google.firebase:firebase-storage:${project.ext.firebase_version}"
3844
compile "com.google.android.gms:play-services-auth:${project.ext.firebase_version}"
3945

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

app/proguard-rules.pro

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,11 @@
2020
# https://firebase-dot-devsite.googleplex.com/docs/auth/android/start/#proguard
2121
-keepattributes Signature
2222
-keepattributes *Annotation*
23+
24+
# See:
25+
# storage/README.md
26+
-assumenosideeffects class android.util.Log {
27+
public static *** w(...);
28+
public static *** d(...);
29+
public static *** v(...);
30+
}

app/src/main/AndroidManifest.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
package="com.firebase.uidemo">
44

55
<uses-permission android:name="android.permission.INTERNET" />
6+
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
67

78
<application
89
android:allowBackup="true"
910
android:icon="@mipmap/ic_launcher"
1011
android:label="@string/app_name"
1112
android:theme="@style/AppTheme">
12-
1313
<activity android:name=".ChooserActivity">
1414
<intent-filter>
1515
<action android:name="android.intent.action.MAIN" />
@@ -27,10 +27,10 @@
2727
<activity
2828
android:name=".auth.AuthUiActivity"
2929
android:label="@string/name_auth_ui" />
30-
3130
<activity
3231
android:name=".auth.SignedInActivity"
3332
android:label="@string/name_auth_ui" />
33+
<activity android:name=".storage.ImageActivity"></activity>
3434
</application>
3535

3636
</manifest>

app/src/main/java/com/firebase/uidemo/ChooserActivity.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import com.firebase.uidemo.auth.AuthUiActivity;
2929
import com.firebase.uidemo.database.ChatActivity;
30+
import com.firebase.uidemo.storage.ImageActivity;
3031

3132
import butterknife.BindView;
3233
import butterknife.ButterKnife;
@@ -37,16 +38,19 @@ public class ChooserActivity extends AppCompatActivity {
3738
private static final Class[] CLASSES = new Class[]{
3839
ChatActivity.class,
3940
AuthUiActivity.class,
41+
ImageActivity.class,
4042
};
4143

4244
private static final int[] DESCRIPTION_NAMES = new int[] {
4345
R.string.name_chat,
44-
R.string.name_auth_ui
46+
R.string.name_auth_ui,
47+
R.string.name_image
4548
};
4649

4750
private static final int[] DESCRIPTION_IDS = new int[] {
4851
R.string.desc_chat,
49-
R.string.desc_auth_ui
52+
R.string.desc_auth_ui,
53+
R.string.desc_image
5054
};
5155

5256
@BindView(R.id.list_view)
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
package com.firebase.uidemo.storage;
2+
3+
import android.Manifest;
4+
import android.content.Intent;
5+
import android.net.Uri;
6+
import android.os.Bundle;
7+
import android.provider.MediaStore;
8+
import android.support.annotation.NonNull;
9+
import android.support.v7.app.AppCompatActivity;
10+
import android.util.Log;
11+
import android.view.View;
12+
import android.widget.Button;
13+
import android.widget.ImageView;
14+
import android.widget.Toast;
15+
16+
import com.bumptech.glide.Glide;
17+
import com.firebase.ui.storage.images.FirebaseImageLoader;
18+
import com.firebase.uidemo.R;
19+
import com.google.android.gms.tasks.OnCompleteListener;
20+
import com.google.android.gms.tasks.OnFailureListener;
21+
import com.google.android.gms.tasks.OnSuccessListener;
22+
import com.google.android.gms.tasks.Task;
23+
import com.google.firebase.auth.AuthResult;
24+
import com.google.firebase.auth.FirebaseAuth;
25+
import com.google.firebase.storage.FirebaseStorage;
26+
import com.google.firebase.storage.StorageReference;
27+
import com.google.firebase.storage.UploadTask;
28+
29+
import java.util.UUID;
30+
31+
import butterknife.BindView;
32+
import butterknife.ButterKnife;
33+
import butterknife.OnClick;
34+
import pub.devrel.easypermissions.AfterPermissionGranted;
35+
import pub.devrel.easypermissions.EasyPermissions;
36+
37+
public class ImageActivity extends AppCompatActivity {
38+
39+
private static final String TAG = "ImageDemo";
40+
private static final int RC_CHOOSE_PHOTO = 101;
41+
private static final int RC_IMAGE_PERMS = 102;
42+
43+
private StorageReference mImageRef;
44+
45+
@BindView(R.id.button_choose_photo)
46+
Button mUploadButton;
47+
48+
@BindView(R.id.button_download_direct)
49+
Button mDownloadDirectButton;
50+
51+
@BindView(R.id.first_image)
52+
ImageView mImageView;
53+
54+
@Override
55+
protected void onCreate(Bundle savedInstanceState) {
56+
super.onCreate(savedInstanceState);
57+
setContentView(R.layout.activity_image);
58+
ButterKnife.bind(this);
59+
60+
// By default, Firebase Storage files require authentication to read or write.
61+
// For this sample to function correctly, enable Anonymous Auth in the Firebase console:
62+
// https://console.firebase.google.com/project/_/authentication/providers
63+
FirebaseAuth.getInstance().signInAnonymously()
64+
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
65+
@Override
66+
public void onComplete(@NonNull Task<AuthResult> task) {
67+
Log.d(TAG, "signInAnonymously:" + task.isSuccessful());
68+
if (!task.isSuccessful()) {
69+
Log.w(TAG, "signInAnonymously", task.getException());
70+
Log.w(TAG, getString(R.string.anonymous_auth_failed_msg));
71+
72+
Toast.makeText(ImageActivity.this,
73+
getString(R.string.anonymous_auth_failed_toast),
74+
Toast.LENGTH_SHORT).show();
75+
}
76+
}
77+
});
78+
}
79+
80+
@Override
81+
public void onActivityResult(int requestCode, int resultCode, Intent data) {
82+
super.onActivityResult(requestCode, resultCode, data);
83+
84+
if (requestCode == RC_CHOOSE_PHOTO) {
85+
if (resultCode == RESULT_OK) {
86+
Uri selectedImage = data.getData();
87+
uploadPhoto(selectedImage);
88+
} else {
89+
Toast.makeText(this, "No image chosen", Toast.LENGTH_SHORT).show();
90+
}
91+
}
92+
}
93+
94+
@Override
95+
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
96+
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
97+
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
98+
}
99+
100+
@OnClick(R.id.button_choose_photo)
101+
@AfterPermissionGranted(RC_IMAGE_PERMS)
102+
protected void choosePhoto() {
103+
String perm = Manifest.permission.READ_EXTERNAL_STORAGE;
104+
if (!EasyPermissions.hasPermissions(this, perm)) {
105+
EasyPermissions.requestPermissions(this, getString(R.string.rational_image_perm),
106+
RC_IMAGE_PERMS, perm);
107+
return;
108+
}
109+
110+
Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
111+
startActivityForResult(i, RC_CHOOSE_PHOTO);
112+
}
113+
114+
protected void uploadPhoto(Uri uri) {
115+
// Reset UI
116+
hideDownloadUI();
117+
Toast.makeText(this, "Uploading...", Toast.LENGTH_SHORT).show();
118+
119+
// Upload to Firebase Storage
120+
String uuid = UUID.randomUUID().toString();
121+
mImageRef = FirebaseStorage.getInstance().getReference(uuid);
122+
mImageRef.putFile(uri)
123+
.addOnSuccessListener(this, new OnSuccessListener<UploadTask.TaskSnapshot>() {
124+
@Override
125+
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
126+
Log.d(TAG, "uploadPhoto:onSuccess:" +
127+
taskSnapshot.getMetadata().getReference().getPath());
128+
Toast.makeText(ImageActivity.this, "Image uploaded",
129+
Toast.LENGTH_SHORT).show();
130+
131+
showDownloadUI();
132+
}
133+
})
134+
.addOnFailureListener(this, new OnFailureListener() {
135+
@Override
136+
public void onFailure(@NonNull Exception e) {
137+
Log.w(TAG, "uploadPhoto:onError", e);
138+
Toast.makeText(ImageActivity.this, "Upload failed",
139+
Toast.LENGTH_SHORT).show();
140+
}
141+
});
142+
}
143+
144+
@OnClick(R.id.button_download_direct)
145+
protected void downloadDirect() {
146+
// Download directly from StorageReference using Glide
147+
Glide.with(this)
148+
.using(new FirebaseImageLoader())
149+
.load(mImageRef)
150+
.centerCrop()
151+
.crossFade()
152+
.into(mImageView);
153+
}
154+
155+
private void hideDownloadUI() {
156+
mDownloadDirectButton.setEnabled(false);
157+
158+
mImageView.setImageResource(0);
159+
mImageView.setVisibility(View.INVISIBLE);
160+
}
161+
162+
private void showDownloadUI() {
163+
mDownloadDirectButton.setEnabled(true);
164+
165+
mImageView.setVisibility(View.VISIBLE);
166+
}
167+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:app="http://schemas.android.com/apk/res-auto"
4+
xmlns:tools="http://schemas.android.com/tools"
5+
android:layout_width="match_parent"
6+
android:layout_height="match_parent"
7+
android:orientation="vertical"
8+
android:paddingBottom="@dimen/activity_vertical_margin"
9+
android:paddingLeft="@dimen/activity_horizontal_margin"
10+
android:paddingRight="@dimen/activity_horizontal_margin"
11+
android:paddingTop="@dimen/activity_vertical_margin"
12+
tools:context="com.firebase.uidemo.storage.ImageActivity">
13+
14+
<TextView
15+
style="@style/TextAppearance.AppCompat.Medium"
16+
android:layout_width="wrap_content"
17+
android:layout_height="wrap_content"
18+
android:text="Upload" />
19+
20+
<Button
21+
android:id="@+id/button_choose_photo"
22+
android:layout_width="wrap_content"
23+
android:layout_height="wrap_content"
24+
android:text="Choose Image" />
25+
26+
<TextView
27+
style="@style/TextAppearance.AppCompat.Medium"
28+
android:layout_width="wrap_content"
29+
android:layout_height="wrap_content"
30+
android:layout_marginTop="20dp"
31+
android:text="Download" />
32+
33+
<LinearLayout
34+
android:layout_width="wrap_content"
35+
android:layout_height="wrap_content"
36+
android:orientation="horizontal">
37+
38+
<Button
39+
android:id="@+id/button_download_direct"
40+
android:layout_width="wrap_content"
41+
android:layout_height="wrap_content"
42+
android:enabled="false"
43+
android:text="Download" />
44+
45+
</LinearLayout>
46+
47+
<ImageView
48+
android:id="@+id/first_image"
49+
android:layout_width="match_parent"
50+
android:layout_height="match_parent"
51+
android:scaleType="centerCrop"
52+
android:src="#E6E6E6"
53+
android:visibility="invisible"
54+
tools:visibility="visible" />
55+
56+
</LinearLayout>

app/src/main/res/values/strings.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33

44
<string name="name_chat">ChatActivity</string>
55
<string name="name_auth_ui">Auth UI demo</string>
6+
<string name="name_image">Storage Image Demo</string>
67

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

1012
<!-- strings for Auth UI demo activities -->
11-
<eat-comment/>
13+
<eat-comment />
1214
<string name="launch_title">FirebaseUI Auth Demo</string>
1315
<string name="sign_in">Start</string>
1416
<string name="green_theme">Green Theme</string>
@@ -42,4 +44,8 @@
4244
<string name="configuration_required">Configuration is required - see README.md</string>
4345
<string name="other_options_header">Other Options:</string>
4446
<string name="enable_smartlock">Enable SmartLock for Passwords</string>
47+
<string name="rational_image_perm">This sample will read an image from local storage to upload to Firebase Storage.</string>
48+
49+
<string name="anonymous_auth_failed_toast">Authentication failed, uploads and downloads will not work.</string>
50+
<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>
4551
</resources>

0 commit comments

Comments
 (0)