android - StorageReference downloadUrl 获取 URL 失败
问题描述
希望我对我在获取图像下载 URL 时犯的错误有一个简单的答案。这是可行的,但在修复了许多其他编译问题后停止了,其中一些与 Gradle 实现版本有关。显然表明我无法理解 Firebase StorageReference 编码文档。我发现大多数程序员都不知道如何为傻瓜编写文档:)。
从我阅读的一些信息中,我也有一个与最佳实践相关的安全问题。感谢您提供的任何答案。
所以这是我的 App Gradle 文件:
//////////////////////////////////
apply plugin: 'com.android.application'
android {
compileSdkVersion versions.compileSdk
buildToolsVersion versions.buildTools
defaultConfig {
applicationId "com.example.cell.der"
//////////////////////////////////////////////////////////////////////////////////////////////////
// The manifest setting tells Google Play that your application can be installed on
// devices with Android 4.0 (API level 14) and higher. If you are using Gradle build files,
// the minSdkVersion setting in the build file overrides the manifest settings:
// <uses-sdk
// android:minSdkVersion="14"
// android:targetSdkVersion="23" />
//////////////////////////////////////////////////////////////////////////////////////////////////
minSdkVersion 14
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true
}
buildTypes {
release {
shrinkResources true // This must be first
minifyEnabled true // This must be after shrinkResources
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
customDebug {
debuggable true
}
debug {
testCoverageEnabled = false
}
}
}
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:animated-vector-drawable:27.1.1'
implementation 'com.android.support:recyclerview-v7:27.1.1'
implementation 'com.android.support:exifinterface:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.android.support:design:27.1.1'
implementation 'com.android.support:cardview-v7:27.1.1'
implementation 'com.android.support:support-v4:27.1.1'
implementation 'com.android.support:support-annotations:27.1.1'
implementation "com.android.support:support-fragment:27.1.1"
implementation 'com.google.firebase:firebase-core:16.0.0'
implementation 'com.google.firebase:firebase-auth:16.0.1'
implementation 'com.google.firebase:firebase-storage:16.0.1'
implementation 'com.google.firebase:firebase-database:16.0.1'
implementation "com.google.firebase:firebase-firestore:17.0.1"
implementation 'com.firebaseui:firebase-ui-storage:0.6.0'
implementation 'com.android.support:palette-v7:27.1.1'
//Compile SDK Version - Glide must be compiled against SDK version 27 (Oreo MR1) or higher.
//Support Library Version - Glide uses support library version 27.
//Compile SDK Version - Glide must be compiled against SDK version 27 (Oreo MR1) or higher.
//Support Library Version - Glide uses support library version 27.
annotationProcessor 'com.github.bumptech.glide:compiler:4.7.1'
implementation("com.github.bumptech.glide:glide:4.7.1")
{
exclude group: "com.android.support"
}
// implementation 'com.github.bumptech.glide:glide:4.7.1'
implementation 'com.lorentzos.swipecards:library:1.0.9'
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
//////////////////////////////////////////////////////////////////////////////////////////////////
// If you use Glide’s annotations on classes implemented in Kotlin, you need to include a kapt
// dependency on Glide’s annotation processor instead of a annotationProcessor dependency
//////////////////////////////////////////////////////////////////////////////////////////////////
//for image crop
implementation "com.theartofdev.edmodo:android-image-cropper:2.4.7"
}
//apply plugin: 'kotlin-kapt'
apply plugin: 'com.google.gms.google-services'
这是我试图获取刚刚在 storage 中成功上传的图像的下载 URL 的地方。当我希望它是 downloadURL 值时,它将数据库中文件路径的位置存储到我的 profileImageURL 变量中。
代码使用下面的 SettingsActivity.java 保存用户数据和图像。
问题是它应该存储类似于以下内容的链接:
https://firebasestorage.googleapis.com/v0/b/appname.appspot.com/o/profileImages%2FpqAIiU7589S64RiTi4rdDhjR6KQ2?alt=media&token=bef1884e-44a0-4229-ad26-89381cf2d03a
而是将文件位置加载到 Firebase 数据库中的 downloadUrl 变量和 profileImageUrl 中。:
gs://appname.appspot.com/profileImages/pqAIiU2389434RiTi4rdDhjR6KQ2
在我开始更改代码以修复其他错误之前,它曾经使用此命令。编译器告诉我 getDownloadUrl() 是未知代码。
//Uri downloadUrl = taskSnapshot.getDownloadUrl(); //Depreciated
它在我的数据库中的样子。一切都或多或少地工作,但图像不会加载到设备上,因为它现在显然没有得到正确的位置。当创建新用户并且“默认”case 语句显示 ic_launcher 图像时,它会抓取图像。此外,我的图像存储在 Firebase 存储的一个名为 profileImages/ 的文件夹中
//////////////////////////////////////////////////
package com.example.cell.der;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
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.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.ChildEventListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageReference;
import com.google.firebase.storage.UploadTask;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class SettingsActivity extends AppCompatActivity {
private EditText mNameField, mPhoneField;
private Button mBack, mConfirm;
private ImageView mProfileImage;
private FirebaseAuth mAuth;
private DatabaseReference mUserDatabase;
private String userId, name, phone, profileImageUrl, userSex;
private Uri resultUri;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
//Get Views (fields/buttons) from XML by using findViewById
mNameField = (EditText) findViewById(R.id.name);
mPhoneField = (EditText) findViewById(R.id.phone);
mProfileImage = (ImageView) findViewById(R.id.profileImage);
mBack = (Button) findViewById(R.id.back);
mConfirm = (Button) findViewById(R.id.confirm);
mAuth = FirebaseAuth.getInstance();
userId = mAuth.getCurrentUser().getUid();
mUserDatabase = FirebaseDatabase.getInstance().getReference().child("Users").child(userId);
getUserInfo();
//Attach onClickListeners to Views (fields/buttons)
mProfileImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, 1);
}
});
mConfirm.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
saveUserInformation();
}
});
mBack.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
return;
}
});
}
....
....
//Save User's information into Firebase database
private void saveUserInformation() {
name = mNameField.getText().toString();
phone = mPhoneField.getText().toString();
Map userInfo = new HashMap();
userInfo.put("name", name);
userInfo.put("phone", phone);
//Update the current values stored in the Firebase Instance for current userId
mUserDatabase.updateChildren(userInfo);
if(resultUri != null){
StorageReference filepath = FirebaseStorage.getInstance().getReference().child("profileImages").child(userId);
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(getApplication().getContentResolver(), resultUri);
} catch (IOException e) {
e.printStackTrace();
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 20, baos);
byte[] data = baos.toByteArray();
UploadTask uploadTask = filepath.putBytes(data);
uploadTask.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
finish();
}
});
uploadTask.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
//Uri downloadUrl = taskSnapshot.getDownloadUrl(); //Depreciated
//final StorageReference downloadUrl = FirebaseStorage.getInstance().getReference("profileImages/").getDownloadUrl();
StorageReference downloadUrl = FirebaseStorage.getInstance().getReference().child("profileImages").child(userId);
Map userInfo = new HashMap();
userInfo.put("profileImageUrl", downloadUrl.toString());
mUserDatabase.updateChildren(userInfo);
finish();
return;
}
});
}else{
finish();
}
我的另一个问题与最佳实践有关。我读到 getDownloadUrl() 不是最好的,因为 URL 是暴露的,有人可能会导致问题(例如 Firebase 数据消耗)。如果是这样,我将如何使这更安全? 如果可能的话,真的在寻找与 Firebase 相关的示例代码以及我如何构建我的代码。 使用 GLide 4.7.1、AS 3.1.2。
解决方案
推荐阅读
- javascript - NotifyJS 在成功时返回代码而不是警报
- deep-learning - 来自 SSD 的预测图像 ID 和框
- c - 为什么我得到一条不存在的新行
- javascript - React 中的 setTimeout 隐式输出数字到 DOM
- python - 如何在kivy中使用浮动布局在应用程序的左下角放置标签?
- nativescript - 使用带有 NativeScript nativescript-pdf-view 插件的 base64 数据显示 PDF
- c++ - 多态性和函数绑定
- python - 值错误:连接轴的所有输入数组维度必须完全匹配
- excel - 显示单元格中的最后 13 个数字以及这 13 个数字后面的任何字母
- mule - 使用 dataweave 2.0 在 mule 4 中按 order by 进行转换