├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── example │ │ └── storage │ │ ├── CloudStorageActivity.java │ │ ├── DownloadActivity.java │ │ ├── MainActivity.java │ │ ├── UploadActivity.java │ │ └── util │ │ ├── Helper.java │ │ └── MyAppGlideModule.java │ └── res │ ├── layout │ ├── activity_cloud_storage.xml │ ├── activity_download.xml │ ├── activity_main.xml │ └── activity_upload.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── logo.png │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | #built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # files for the dex VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # generated files 12 | bin/ 13 | gen/ 14 | out/ 15 | 16 | # Local configuration file (sdk path, etc) 17 | local.properties 18 | 19 | # Windows thumbnail db 20 | Thumbs.db 21 | 22 | # OSX files 23 | .DS_Store 24 | 25 | # Log Files 26 | *.log 27 | 28 | # Android Studio 29 | *.iml 30 | .gradle/ 31 | build/ 32 | captures/ 33 | .navigation/ 34 | 35 | # Intellij IDEA 36 | .idea/ 37 | 38 | # Eclipse project files 39 | .classpath 40 | .project 41 | 42 | # Proguard folder generated by Eclipse 43 | proguard/ 44 | 45 | # Eclipse Metadata 46 | .metadata/ 47 | 48 | # Keystore files 49 | *.jks 50 | 51 | .externalNativeBuild 52 | 53 | google-services.json 54 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Firebase Storage 2 | Firebase Storage code guideline for Android developers 3 | 4 | ## Prerequisites 5 | * Supported Android 4.1 or newer 6 | * Android Studio 3.3.2 or higher 7 | * google-services.json in app-level folder 8 | 9 | ## Features 10 | * No Authentication usage 11 | * Create references 12 | * Upload files 13 | * Download files 14 | * Use file metadata 15 | * Delete files 16 | 17 | ## Screenshots 18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | ## Blog 27 | [Firebase Storage](https://medium.com/@jirawatee/%E0%B8%A3%E0%B8%B9%E0%B9%89%E0%B8%88%E0%B8%B1%E0%B8%81-firebase-storage-%E0%B8%95%E0%B8%B1%E0%B9%89%E0%B8%87%E0%B9%81%E0%B8%95%E0%B9%88-zero-%E0%B8%88%E0%B8%99%E0%B9%80%E0%B8%9B%E0%B9%87%E0%B8%99-hero-e65db2d1873f) 28 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion compileAndTargetSdk 5 | buildToolsVersion '30.0.3' 6 | 7 | defaultConfig { 8 | applicationId "com.example.storage" 9 | minSdkVersion 21 10 | targetSdkVersion compileAndTargetSdk 11 | versionCode 1 12 | versionName '1.0' 13 | resConfigs('en', 'xxxhdpi') 14 | ndk { 15 | abiFilters "x86", "x86_64", "arm64-v8a", "armeabi-v7a" 16 | } 17 | } 18 | 19 | buildTypes { 20 | release { 21 | minifyEnabled true 22 | shrinkResources true 23 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 24 | } 25 | debug { 26 | splits.abi.enable = false 27 | splits.density.enable = false 28 | aaptOptions.cruncherEnabled = false 29 | } 30 | } 31 | } 32 | 33 | dependencies { 34 | implementation 'androidx.appcompat:appcompat:1.2.0' 35 | implementation "com.google.firebase:firebase-analytics:18.0.3" 36 | implementation "com.google.firebase:firebase-storage:19.2.2" 37 | implementation "com.github.bumptech.glide:glide:$glideLibraryVersion" 38 | annotationProcessor "com.github.bumptech.glide:compiler:$glideLibraryVersion" 39 | annotationProcessor 'androidx.annotation:annotation:1.2.0' 40 | } 41 | apply plugin: 'com.google.gms.google-services' -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | -keepattributes Signature 2 | -keepattributes *Annotation* 3 | -keepattributes EnclosingMethod 4 | -keepattributes InnerClasses 5 | 6 | -keep public class * implements com.bumptech.glide.module.GlideModule 7 | -keep public class * extends com.bumptech.glide.module.AppGlideModule 8 | -keep public enum com.bumptech.glide.load.ImageHeaderParser$** { 9 | **[] $VALUES; 10 | public *; 11 | } 12 | 13 | # If you're targeting any API level less than Android API 27, also include: 14 | -dontwarn com.bumptech.glide.load.resource.bitmap.VideoDecoder 15 | 16 | -assumenosideeffects class android.util.Log { 17 | public static boolean isLoggable(java.lang.String, int); 18 | public static int v(...); 19 | public static int i(...); 20 | public static int w(...); 21 | public static int d(...); 22 | public static int e(...); 23 | public static int wtf(...); 24 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/storage/CloudStorageActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.storage; 2 | 3 | import android.content.Intent; 4 | import android.net.Uri; 5 | import android.os.Bundle; 6 | import android.provider.MediaStore; 7 | import androidx.appcompat.app.AppCompatActivity; 8 | import android.view.View; 9 | import android.widget.ImageView; 10 | 11 | import com.bumptech.glide.Glide; 12 | import com.example.storage.util.Helper; 13 | import com.google.android.gms.tasks.OnSuccessListener; 14 | import com.google.firebase.storage.FirebaseStorage; 15 | import com.google.firebase.storage.OnProgressListener; 16 | import com.google.firebase.storage.StorageReference; 17 | import com.google.firebase.storage.UploadTask; 18 | 19 | import java.io.File; 20 | 21 | public class CloudStorageActivity extends AppCompatActivity implements View.OnClickListener{ 22 | private StorageReference storageRef, imageRef; 23 | private static final int RC_UPLOAD_FILE = 102; 24 | private ImageView mImageView; 25 | 26 | @Override 27 | protected void onCreate(Bundle savedInstanceState) { 28 | super.onCreate(savedInstanceState); 29 | setContentView(R.layout.activity_cloud_storage); 30 | mImageView = findViewById(R.id.imv); 31 | findViewById(R.id.btn_upload).setOnClickListener(this); 32 | 33 | // Get instance and specify regional 34 | FirebaseStorage storage = FirebaseStorage.getInstance(); 35 | 36 | // Get reference 37 | storageRef = storage.getReference(); 38 | } 39 | 40 | @Override 41 | public void onClick(View view) { 42 | switch (view.getId()) { 43 | case R.id.btn_upload: 44 | Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); 45 | startActivityForResult(intent, RC_UPLOAD_FILE); 46 | break; 47 | } 48 | } 49 | 50 | @Override 51 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 52 | super.onActivityResult(requestCode, resultCode, data); 53 | if (resultCode == RESULT_OK) { 54 | String path = Helper.getPath(this, data.getData()); 55 | switch (requestCode) { 56 | case RC_UPLOAD_FILE: 57 | uploadFromFile(path); 58 | break; 59 | } 60 | } 61 | } 62 | 63 | private void uploadFromFile(String path) { 64 | Uri file = Uri.fromFile(new File(path)); 65 | 66 | // Get image reference from file 67 | imageRef = storageRef.child(file.getLastPathSegment()); 68 | 69 | // Create Upload Task 70 | UploadTask uploadTask = imageRef.putFile(file); 71 | 72 | Helper.initProgressDialog(this); 73 | Helper.mProgressDialog.show(); 74 | 75 | uploadTask.addOnSuccessListener(new OnSuccessListener() { 76 | @Override 77 | public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { 78 | Helper.dismissProgressDialog(); 79 | imageRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener() { 80 | @Override 81 | public void onSuccess(Uri uri) { 82 | Glide.with(CloudStorageActivity.this).load(uri.toString()).thumbnail(0.1f).into(mImageView); 83 | } 84 | }); 85 | } 86 | }).addOnProgressListener(new OnProgressListener() { 87 | @Override 88 | public void onProgress(UploadTask.TaskSnapshot taskSnapshot) { 89 | int progress = (int) ((100 * taskSnapshot.getBytesTransferred()) / taskSnapshot.getTotalByteCount()); 90 | Helper.setProgress(progress); 91 | } 92 | }); 93 | // Add upload listenter 94 | } 95 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/storage/DownloadActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.storage; 2 | 3 | import android.content.DialogInterface; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.net.Uri; 7 | import android.os.Bundle; 8 | import android.os.Environment; 9 | import android.view.View; 10 | import android.widget.ImageView; 11 | import android.widget.TextView; 12 | 13 | import androidx.annotation.NonNull; 14 | import androidx.appcompat.app.AppCompatActivity; 15 | 16 | import com.example.storage.util.Helper; 17 | import com.google.android.gms.tasks.OnFailureListener; 18 | import com.google.android.gms.tasks.OnSuccessListener; 19 | import com.google.firebase.storage.FileDownloadTask; 20 | import com.google.firebase.storage.FirebaseStorage; 21 | import com.google.firebase.storage.OnProgressListener; 22 | import com.google.firebase.storage.StorageMetadata; 23 | import com.google.firebase.storage.StorageReference; 24 | 25 | import java.io.File; 26 | import java.io.IOException; 27 | import java.util.UUID; 28 | 29 | public class DownloadActivity extends AppCompatActivity implements View.OnClickListener{ 30 | private ImageView mImageView; 31 | private StorageReference imageRef; 32 | private TextView mTextView; 33 | 34 | @Override 35 | protected void onCreate(Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | setContentView(R.layout.activity_download); 38 | bindWidget(); 39 | FirebaseStorage storage = FirebaseStorage.getInstance(); 40 | //FirebaseStorage storage = FirebaseStorage.getInstance("gs://jirawatee-eastern"); 41 | //FirebaseStorage storage = FirebaseStorage.getInstance("gs://jirawatee-northeastern"); 42 | //FirebaseStorage storage = FirebaseStorage.getInstance("gs://jirawatee-europe"); 43 | //FirebaseStorage storage = FirebaseStorage.getInstance("gs://jirawatee-easternus"); 44 | //FirebaseStorage storage = FirebaseStorage.getInstance("gs://jirawatee-europeunion"); 45 | 46 | StorageReference storageRef = storage.getReference(); 47 | imageRef = storageRef.child("photos/kaizen.png"); 48 | } 49 | 50 | @Override 51 | public void onClick(View view) { 52 | switch (view.getId()) { 53 | case R.id.button_download_in_memory: 54 | downloadInMemory(); 55 | break; 56 | case R.id.button_download_in_file: 57 | downloadInLocalFile(); 58 | break; 59 | case R.id.button_download_via_url: 60 | downloadDataViaUrl(); 61 | break; 62 | case R.id.button_get_metadata: 63 | getMetadata(); 64 | break; 65 | case R.id.button_update_metadata: 66 | updateMetaData(); 67 | break; 68 | case R.id.button_delete_file: 69 | deleteFile(); 70 | break; 71 | } 72 | } 73 | 74 | @Override 75 | protected void onDestroy() { 76 | super.onDestroy(); 77 | Helper.dismissProgressDialog(); 78 | Helper.dismissDialog(); 79 | } 80 | 81 | private void bindWidget() { 82 | mImageView = findViewById(R.id.imageview); 83 | mTextView = findViewById(R.id.textview); 84 | findViewById(R.id.button_download_in_memory).setOnClickListener(this); 85 | findViewById(R.id.button_download_in_file).setOnClickListener(this); 86 | findViewById(R.id.button_download_via_url).setOnClickListener(this); 87 | findViewById(R.id.button_get_metadata).setOnClickListener(this); 88 | findViewById(R.id.button_update_metadata).setOnClickListener(this); 89 | findViewById(R.id.button_delete_file).setOnClickListener(this); 90 | } 91 | 92 | private void downloadInMemory() { 93 | //long ONE_MEGABYTE = 1024 * 1024; 94 | Helper.showDialog(this); 95 | imageRef.getBytes(Long.MAX_VALUE).addOnSuccessListener(new OnSuccessListener() { 96 | @Override 97 | public void onSuccess(byte[] bytes) { 98 | Helper.dismissDialog(); 99 | Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); 100 | mImageView.setImageBitmap(bitmap); 101 | } 102 | }).addOnFailureListener(new OnFailureListener() { 103 | @Override 104 | public void onFailure(@NonNull Exception exception) { 105 | Helper.dismissDialog(); 106 | mTextView.setText(String.format("Failure: %s", exception.getMessage())); 107 | } 108 | }); 109 | } 110 | 111 | private void downloadInLocalFile() { 112 | File dir = new File(Environment.getExternalStorageDirectory() + "/photos"); 113 | final File file = new File(dir, UUID.randomUUID().toString() + ".png"); 114 | try { 115 | if (!dir.exists()) { 116 | dir.mkdir(); 117 | } 118 | file.createNewFile(); 119 | } catch (IOException e) { 120 | e.printStackTrace(); 121 | } 122 | 123 | final FileDownloadTask fileDownloadTask = imageRef.getFile(file); 124 | Helper.initProgressDialog(this); 125 | Helper.mProgressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() { 126 | @Override 127 | public void onClick(DialogInterface dialogInterface, int i) { 128 | fileDownloadTask.cancel(); 129 | } 130 | }); 131 | Helper.mProgressDialog.show(); 132 | 133 | fileDownloadTask.addOnSuccessListener(new OnSuccessListener() { 134 | @Override 135 | public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) { 136 | Helper.dismissProgressDialog(); 137 | mTextView.setText(file.getPath()); 138 | mImageView.setImageURI(Uri.fromFile(file)); 139 | } 140 | }).addOnFailureListener(new OnFailureListener() { 141 | @Override 142 | public void onFailure(@NonNull Exception exception) { 143 | Helper.dismissProgressDialog(); 144 | mTextView.setText(String.format("Failure: %s", exception.getMessage())); 145 | } 146 | }).addOnProgressListener(new OnProgressListener() { 147 | @Override 148 | public void onProgress(FileDownloadTask.TaskSnapshot taskSnapshot) { 149 | int progress = (int) ((100 * taskSnapshot.getBytesTransferred()) / taskSnapshot.getTotalByteCount()); 150 | Helper.setProgress(progress); 151 | } 152 | }); 153 | } 154 | 155 | private void downloadDataViaUrl() { 156 | Helper.showDialog(this); 157 | imageRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener() { 158 | @Override 159 | public void onSuccess(Uri uri) { 160 | Helper.dismissDialog(); 161 | mTextView.setText(uri.toString()); 162 | } 163 | }).addOnFailureListener(new OnFailureListener() { 164 | @Override 165 | public void onFailure(@NonNull Exception exception) { 166 | Helper.dismissDialog(); 167 | mTextView.setText(String.format("Failure: %s", exception.getMessage())); 168 | } 169 | }); 170 | } 171 | 172 | private void getMetadata() { 173 | Helper.showDialog(this); 174 | imageRef.getMetadata().addOnSuccessListener(new OnSuccessListener() { 175 | @Override 176 | public void onSuccess(StorageMetadata storageMetadata) { 177 | Helper.dismissDialog(); 178 | mTextView.setText(String.format("Country: %s", storageMetadata.getCustomMetadata("country"))); 179 | } 180 | }).addOnFailureListener(new OnFailureListener() { 181 | @Override 182 | public void onFailure(@NonNull Exception exception) { 183 | Helper.dismissDialog(); 184 | mTextView.setText(String.format("Failure: %s", exception.getMessage())); 185 | } 186 | }); 187 | } 188 | 189 | private void updateMetaData() { 190 | Helper.showDialog(this); 191 | StorageMetadata metadata = new StorageMetadata.Builder().setCustomMetadata("country", "Thailand").build(); 192 | imageRef.updateMetadata(metadata).addOnSuccessListener(new OnSuccessListener() { 193 | @Override 194 | public void onSuccess(StorageMetadata storageMetadata) { 195 | Helper.dismissDialog(); 196 | mTextView.setText(String.format("Country: %s", storageMetadata.getCustomMetadata("country"))); 197 | } 198 | }).addOnFailureListener(new OnFailureListener() { 199 | @Override 200 | public void onFailure(@NonNull Exception exception) { 201 | Helper.dismissDialog(); 202 | mTextView.setText(String.format("Failure: %s", exception.getMessage())); 203 | } 204 | }); 205 | } 206 | 207 | private void deleteFile() { 208 | Helper.showDialog(this); 209 | imageRef.delete().addOnSuccessListener(new OnSuccessListener() { 210 | @Override 211 | public void onSuccess(Void aVoid) { 212 | Helper.dismissDialog(); 213 | mImageView.setImageDrawable(null); 214 | mTextView.setText(String.format("%s was deleted.", imageRef.getPath())); 215 | } 216 | }).addOnFailureListener(new OnFailureListener() { 217 | @Override 218 | public void onFailure(@NonNull Exception exception) { 219 | Helper.dismissDialog(); 220 | mTextView.setText(String.format("Failure: %s", exception.getMessage())); 221 | } 222 | }); 223 | } 224 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/storage/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.storage; 2 | 3 | import android.content.DialogInterface; 4 | import android.content.Intent; 5 | import android.content.pm.PackageManager; 6 | import android.net.Uri; 7 | import android.os.Bundle; 8 | import android.provider.Settings; 9 | import androidx.annotation.NonNull; 10 | import androidx.core.app.ActivityCompat; 11 | import androidx.appcompat.app.AlertDialog; 12 | import androidx.appcompat.app.AppCompatActivity; 13 | import android.view.View; 14 | 15 | public class MainActivity extends AppCompatActivity implements View.OnClickListener{ 16 | private static final int RC_STORAGE_PERMS1 = 101; 17 | private static final int RC_STORAGE_PERMS2 = 102; 18 | private int hasWriteExtStorePMS; 19 | 20 | @Override 21 | protected void onCreate(Bundle savedInstanceState) { 22 | super.onCreate(savedInstanceState); 23 | setContentView(R.layout.activity_main); 24 | findViewById(R.id.btn_upload).setOnClickListener(this); 25 | findViewById(R.id.btn_download).setOnClickListener(this); 26 | findViewById(R.id.btn_cloud_storage).setOnClickListener(this); 27 | } 28 | 29 | @Override 30 | public void onRequestPermissionsResult(final int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 31 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 32 | switch (requestCode) { 33 | case RC_STORAGE_PERMS1: 34 | case RC_STORAGE_PERMS2: 35 | if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 36 | if (requestCode == RC_STORAGE_PERMS1) { 37 | startActivity(new Intent(this, UploadActivity.class)); 38 | } else { 39 | startActivity(new Intent(this, DownloadActivity.class)); 40 | } 41 | } else { 42 | AlertDialog.Builder alert = new AlertDialog.Builder(this); 43 | alert.setMessage("You need to allow permission"); 44 | alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { 45 | @Override 46 | public void onClick(DialogInterface dialogInterface, int i) { 47 | dialogInterface.dismiss(); 48 | Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); 49 | intent.setData(Uri.parse("package:" + getPackageName())); 50 | startActivityForResult(intent, requestCode); 51 | } 52 | }); 53 | alert.setCancelable(false); 54 | alert.show(); 55 | } 56 | break; 57 | } 58 | } 59 | 60 | @Override 61 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 62 | super.onActivityResult(requestCode, resultCode, data); 63 | switch (requestCode) { 64 | case RC_STORAGE_PERMS1: 65 | case RC_STORAGE_PERMS2: 66 | hasWriteExtStorePMS = ActivityCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE); 67 | if (hasWriteExtStorePMS == PackageManager.PERMISSION_GRANTED) { 68 | if (requestCode == RC_STORAGE_PERMS1) { 69 | startActivity(new Intent(this, UploadActivity.class)); 70 | } else { 71 | startActivity(new Intent(this, DownloadActivity.class)); 72 | } 73 | } else { 74 | ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, RC_STORAGE_PERMS2); 75 | } 76 | break; 77 | } 78 | } 79 | 80 | @Override 81 | public void onClick(View view) { 82 | switch (view.getId()) { 83 | case R.id.btn_upload: 84 | hasWriteExtStorePMS = ActivityCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE); 85 | if (hasWriteExtStorePMS == PackageManager.PERMISSION_GRANTED) { 86 | startActivity(new Intent(this, UploadActivity.class)); 87 | } else { 88 | ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, RC_STORAGE_PERMS1); 89 | } 90 | break; 91 | case R.id.btn_download: 92 | hasWriteExtStorePMS = ActivityCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE); 93 | if (hasWriteExtStorePMS == PackageManager.PERMISSION_GRANTED) { 94 | startActivity(new Intent(this, DownloadActivity.class)); 95 | } else { 96 | ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, RC_STORAGE_PERMS2); 97 | } 98 | break; 99 | case R.id.btn_cloud_storage: 100 | startActivity(new Intent(this, CloudStorageActivity.class)); 101 | break; 102 | } 103 | } 104 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/storage/UploadActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.storage; 2 | 3 | import android.content.DialogInterface; 4 | import android.content.Intent; 5 | import android.graphics.Bitmap; 6 | import android.net.Uri; 7 | import android.os.Bundle; 8 | import android.provider.MediaStore; 9 | import androidx.annotation.NonNull; 10 | import androidx.appcompat.app.AppCompatActivity; 11 | import android.util.Log; 12 | import android.view.View; 13 | import android.widget.ImageView; 14 | import android.widget.TextView; 15 | 16 | import com.example.storage.util.Helper; 17 | import com.google.android.gms.tasks.OnFailureListener; 18 | import com.google.android.gms.tasks.OnSuccessListener; 19 | import com.google.firebase.storage.FirebaseStorage; 20 | import com.google.firebase.storage.OnPausedListener; 21 | import com.google.firebase.storage.OnProgressListener; 22 | import com.google.firebase.storage.StorageReference; 23 | import com.google.firebase.storage.UploadTask; 24 | 25 | import java.io.ByteArrayOutputStream; 26 | import java.io.File; 27 | import java.io.FileInputStream; 28 | import java.io.FileNotFoundException; 29 | import java.io.InputStream; 30 | 31 | public class UploadActivity extends AppCompatActivity implements View.OnClickListener{ 32 | private static final String TAG = "UploadActivity"; 33 | private static final int RC_UPLOAD_STREAM = 101; 34 | private static final int RC_UPLOAD_FILE = 102; 35 | private ImageView mImageView; 36 | private StorageReference folderRef, imageRef; 37 | private TextView mTextView; 38 | private UploadTask mUploadTask; 39 | 40 | @Override 41 | protected void onCreate(Bundle savedInstanceState) { 42 | super.onCreate(savedInstanceState); 43 | setContentView(R.layout.activity_upload); 44 | bindWidget(); 45 | 46 | FirebaseStorage storage = FirebaseStorage.getInstance(); 47 | //FirebaseStorage storage = FirebaseStorage.getInstance("gs://jirawatee-eastern"); 48 | //FirebaseStorage storage = FirebaseStorage.getInstance("gs://jirawatee-northeastern"); 49 | //FirebaseStorage storage = FirebaseStorage.getInstance("gs://jirawatee-europe"); 50 | //FirebaseStorage storage = FirebaseStorage.getInstance("gs://jirawatee-easternus"); 51 | //FirebaseStorage storage = FirebaseStorage.getInstance("gs://jirawatee-europeunion"); 52 | StorageReference storageRef = storage.getReference(); 53 | folderRef = storageRef.child("photos"); 54 | imageRef = folderRef.child("firebase.png"); 55 | 56 | Log.d(TAG, imageRef.getPath()); 57 | Log.d(TAG, imageRef.getParent().getPath()); 58 | 59 | } 60 | 61 | @Override 62 | public void onClick(View view) { 63 | Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); 64 | switch (view.getId()) { 65 | case R.id.button_upload_from_memory: 66 | uploadFromDataInMemory(); 67 | break; 68 | case R.id.button_upload_from_stream: 69 | startActivityForResult(intent, RC_UPLOAD_STREAM); 70 | break; 71 | case R.id.button_upload_from_file: 72 | startActivityForResult(intent, RC_UPLOAD_FILE); 73 | break; 74 | case R.id.button_upload_resume: 75 | Helper.mProgressDialog.show(); 76 | mUploadTask.resume(); 77 | break; 78 | } 79 | } 80 | 81 | @Override 82 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 83 | super.onActivityResult(requestCode, resultCode, data); 84 | if (resultCode == RESULT_OK) { 85 | String path = Helper.getPath(this, Uri.parse(data.getData().toString())); 86 | switch (requestCode) { 87 | case RC_UPLOAD_STREAM: 88 | uploadFromStream(path); 89 | break; 90 | case RC_UPLOAD_FILE: 91 | uploadFromFile(path); 92 | break; 93 | } 94 | } 95 | } 96 | 97 | @Override 98 | protected void onDestroy() { 99 | super.onDestroy(); 100 | Helper.dismissProgressDialog(); 101 | Helper.dismissDialog(); 102 | } 103 | 104 | private void bindWidget() { 105 | mImageView = findViewById(R.id.imageview); 106 | mTextView = findViewById(R.id.textview); 107 | findViewById(R.id.button_upload_from_memory).setOnClickListener(this); 108 | findViewById(R.id.button_upload_from_stream).setOnClickListener(this); 109 | findViewById(R.id.button_upload_from_file).setOnClickListener(this); 110 | findViewById(R.id.button_upload_resume).setOnClickListener(this); 111 | } 112 | 113 | private void uploadFromDataInMemory() { 114 | Helper.showDialog(this); 115 | // Get the data from an ImageView as bytes 116 | mImageView.setDrawingCacheEnabled(true); 117 | mImageView.buildDrawingCache(); 118 | Bitmap bitmap = mImageView.getDrawingCache(); 119 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 120 | bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos); 121 | byte[] data = baos.toByteArray(); 122 | 123 | mUploadTask = imageRef.putBytes(data); 124 | mUploadTask.addOnFailureListener(new OnFailureListener() { 125 | @Override 126 | public void onFailure(@NonNull Exception exception) { 127 | Helper.dismissDialog(); 128 | mTextView.setText(String.format("Failure: %s", exception.getMessage())); 129 | } 130 | }).addOnSuccessListener(new OnSuccessListener() { 131 | @Override 132 | public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { 133 | // taskSnapshot.getMetadata() contains file metadata such as size, content-type, and download URL. 134 | Helper.dismissDialog(); 135 | 136 | imageRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener() { 137 | @Override 138 | public void onSuccess(Uri uri) { 139 | mTextView.setText(uri.toString()); 140 | } 141 | }); 142 | } 143 | }); 144 | } 145 | 146 | private void uploadFromStream(String path) { 147 | Helper.showDialog(this); 148 | InputStream stream = null; 149 | try { 150 | stream = new FileInputStream(new File(path)); 151 | } catch (FileNotFoundException e) { 152 | e.printStackTrace(); 153 | } 154 | mUploadTask = imageRef.putStream(stream); 155 | mUploadTask.addOnFailureListener(new OnFailureListener() { 156 | @Override 157 | public void onFailure(@NonNull Exception exception) { 158 | Helper.dismissDialog(); 159 | mTextView.setText(String.format("Failure: %s", exception.getMessage())); 160 | } 161 | }).addOnSuccessListener(new OnSuccessListener() { 162 | @Override 163 | public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { 164 | Helper.dismissDialog(); 165 | imageRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener() { 166 | @Override 167 | public void onSuccess(Uri uri) { 168 | mTextView.setText(uri.toString()); 169 | } 170 | }); 171 | } 172 | }); 173 | } 174 | 175 | private void uploadFromFile(String path) { 176 | Uri file = Uri.fromFile(new File(path)); 177 | final StorageReference imageRef = folderRef.child(file.getLastPathSegment()); 178 | //StorageMetadata metadata = new StorageMetadata.Builder().setContentType("image/jpg").build(); 179 | //UploadTask uploadTask = imageRef.putFile(file, metadata); 180 | mUploadTask = imageRef.putFile(file); 181 | 182 | Helper.initProgressDialog(this); 183 | Helper.mProgressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() { 184 | @Override 185 | public void onClick(DialogInterface dialogInterface, int i) { 186 | mUploadTask.cancel(); 187 | } 188 | }); 189 | Helper.mProgressDialog.setButton(DialogInterface.BUTTON_NEUTRAL, "Pause", new DialogInterface.OnClickListener() { 190 | @Override 191 | public void onClick(DialogInterface dialogInterface, int i) { 192 | mUploadTask.pause(); 193 | } 194 | }); 195 | Helper.mProgressDialog.show(); 196 | 197 | mUploadTask.addOnFailureListener(new OnFailureListener() { 198 | @Override 199 | public void onFailure(@NonNull Exception exception) { 200 | Helper.dismissProgressDialog(); 201 | mTextView.setText(String.format("Failure: %s", exception.getMessage())); 202 | } 203 | }).addOnSuccessListener(new OnSuccessListener() { 204 | @Override 205 | public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { 206 | Helper.dismissProgressDialog(); 207 | findViewById(R.id.button_upload_resume).setVisibility(View.GONE); 208 | imageRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener() { 209 | @Override 210 | public void onSuccess(Uri uri) { 211 | mTextView.setText(uri.toString()); 212 | } 213 | }); 214 | } 215 | }).addOnProgressListener(new OnProgressListener() { 216 | @Override 217 | public void onProgress(UploadTask.TaskSnapshot taskSnapshot) { 218 | int progress = (int) ((100 * taskSnapshot.getBytesTransferred()) / taskSnapshot.getTotalByteCount()); 219 | Helper.setProgress(progress); 220 | } 221 | }).addOnPausedListener(new OnPausedListener() { 222 | @Override 223 | public void onPaused(UploadTask.TaskSnapshot taskSnapshot) { 224 | findViewById(R.id.button_upload_resume).setVisibility(View.VISIBLE); 225 | mTextView.setText(R.string.upload_paused); 226 | } 227 | }); 228 | } 229 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/storage/util/Helper.java: -------------------------------------------------------------------------------- 1 | package com.example.storage.util; 2 | 3 | import android.app.Dialog; 4 | import android.app.ProgressDialog; 5 | import android.content.Context; 6 | import android.database.Cursor; 7 | import android.net.Uri; 8 | import android.provider.MediaStore; 9 | import android.widget.LinearLayout; 10 | import android.widget.ProgressBar; 11 | 12 | import com.example.storage.R; 13 | 14 | public class Helper { 15 | private static Dialog mDialog; 16 | public static ProgressDialog mProgressDialog; 17 | 18 | public static String getPath(Context context, Uri uri) { 19 | String[] projection = {MediaStore.Images.Media.DATA}; 20 | Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null); 21 | int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); 22 | cursor.moveToFirst(); 23 | String path = cursor.getString(column_index); 24 | cursor.close(); 25 | return path; 26 | } 27 | 28 | public static void showDialog(Context context) { 29 | mDialog = new Dialog(context, R.style.NewDialog); 30 | mDialog.addContentView( 31 | new ProgressBar(context), 32 | new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT) 33 | ); 34 | mDialog.setCancelable(true); 35 | mDialog.show(); 36 | } 37 | 38 | public static void dismissDialog() { 39 | if (mDialog != null && mDialog.isShowing()) { 40 | mDialog.dismiss(); 41 | } 42 | } 43 | 44 | public static void initProgressDialog(Context context) { 45 | mProgressDialog = new ProgressDialog(context); 46 | mProgressDialog.setMessage(context.getString(R.string.loading)); 47 | mProgressDialog.setCancelable(false); 48 | mProgressDialog.setMax(100); 49 | mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 50 | } 51 | 52 | public static void setProgress(int i) { 53 | mProgressDialog.setProgress(i); 54 | } 55 | 56 | public static void dismissProgressDialog() { 57 | if (mProgressDialog != null && mProgressDialog.isShowing()) { 58 | mProgressDialog.dismiss(); 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/storage/util/MyAppGlideModule.java: -------------------------------------------------------------------------------- 1 | package com.example.storage.util; 2 | 3 | import com.bumptech.glide.annotation.GlideModule; 4 | import com.bumptech.glide.module.AppGlideModule; 5 | 6 | @GlideModule 7 | public final class MyAppGlideModule extends AppGlideModule { 8 | @Override 9 | public boolean isManifestParsingEnabled() { 10 | return false; 11 | } 12 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_cloud_storage.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | 18 |