java - 我无法使用 Firebase 存储编辑封面图片和个人资料图片。我的程序有什么问题?
问题描述
我在我的项目中添加了用户配置文件页面,即 ProfileFragment.java,它的布局文件是 fragment_profile.xml。我想更新用户信息,如姓名、描述、个人资料图片和封面。我的程序没有错误,名称和描述更新成功但封面和头像没有更新?我的代码有什么问题?
这是我的 ProfileFragment.java
public class ProfileFragment extends Fragment {
//Log Statment
private static final String TAG = "ProfileFragment";
//firebase auth
FirebaseAuth firebaseAuth;
FirebaseUser user;
FirebaseDatabase firebaseDatabase;
DatabaseReference databaseReference;
//firabase storage
StorageReference storageReference;
//profil resminin ve kapak resminin nerede depolanacağının yolu
String storagePath = "Users_Profile_Cover_Imgs/";
//layout views
ImageView avatar, coverPhoto;
TextView nameTxt, emailTxt, descTxt;
FloatingActionButton fab;
//Progress Dialog
ProgressDialog pd;
//permissions
private static final int CAMERA_REQUESTED_CODE = 100;
private static final int STORAGE_REQUESTED_CODE = 200;
private static final int IMAGE_PICK_GALLERY_CODE = 300;
private static final int IMAGE_PICK_CAMERA_CODE = 400;
//izinler için gerekli arrayler
String cameraPermissions[];
String storagePermissions[];
//seçilen resmin uri adresi
Uri image_uri;
//profil fotografı yoksa kapak fotografımı kontrol et
String profileORCoverPhoto;
public ProfileFragment() {
//boş public constructor gerekli
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_profile, container, false);
//init firebase
firebaseAuth = FirebaseAuth.getInstance();
user = firebaseAuth.getCurrentUser();
firebaseDatabase = FirebaseDatabase.getInstance();
databaseReference = firebaseDatabase.getReference("Users");
//init layout views
avatar = view.findViewById(R.id.avatar);
coverPhoto = view.findViewById(R.id.coverPhoto);
nameTxt = view.findViewById(R.id.nameTxt);
emailTxt = view.findViewById(R.id.emailTxt);
descTxt = view.findViewById(R.id.descTxt);
fab = view.findViewById(R.id.fab);
pd = new ProgressDialog(getActivity());
//izin arrayleri
cameraPermissions = new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE};
storagePermissions = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
/* giriş yapan kullanıcıların bilgilerini email yada uid kullanarak çekmek zorundayız
Kullanıcı detaylarını email adreslerini kullanarak çekicez
orderbyChild query kullanarak giriş yapılan email ile email key ini eşleştirerek kullanıcı detaylarına ulaşılıyor
*/
Query query = databaseReference.orderByChild("email").equalTo(user.getEmail());
query.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
//gerekli veriler gelene kadar kontrol et
for (DataSnapshot ds: snapshot.getChildren()){
//verileri almak için
String name = ""+ ds.child("name").getValue();
String email = ""+ ds.child("email").getValue();
String desc = ""+ ds.child("desc").getValue();
String image = ""+ ds.child("image").getValue();
String cover = ""+ ds.child("cover").getValue();
//set data
nameTxt.setText(name);
emailTxt.setText(email);
descTxt.setText(desc);
Log.d(TAG, "onDataChange: \nName: "+name+" email: "+ email);
try {
// resim alınırsa ayarla
Picasso.get().load(image).into(avatar);
} catch (Exception e){
// resim alınırken herangi bir sıkıntı varsa varsayılan olarak ayarla
Picasso.get().load(R.drawable.add_photo_foreground).into(avatar);
}
try {
// kapak resimi alınırsa ayarla
Picasso.get().load(cover).into(coverPhoto);
} catch (Exception e){
// kapak resmi alınırken herangi bir sıkıntı varsa varsayılan olarak ayarla
Picasso.get().load(R.drawable.default_cover_photo).into(coverPhoto);
}
}
Log.d(TAG, "onDataChange: Data is empty");
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
Log.d(TAG, "onCancelled: "+error);
}
});
//fab button onClick özelliği ekleme
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//edit profile dialog göster
showEditProfileDialog();
}
});
return view;
}
private void requestStoragePermission(){
//runtime depolama izinleri isteme
requestPermissions(storagePermissions, STORAGE_REQUESTED_CODE);
}
private void requestCameraPermission(){
//runtime depolama izinleri isteme
requestPermissions(cameraPermissions, CAMERA_REQUESTED_CODE);
}
private boolean checkStoragePermission(){
//depolama izinlerini kontrol et, etkinse true, değilse false döndür
boolean result = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)
== (PackageManager.PERMISSION_GRANTED);
return result;
}
private boolean checkCameraPermission(){
//depolama izinlerini kontrol et, etkinse true, değilse false döndür
boolean result = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA)
== (PackageManager.PERMISSION_GRANTED);
boolean result1 = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)
== (PackageManager.PERMISSION_GRANTED);
return result && result1;
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
//Bu yöntem, kullanıcı izin isteği iletişim kutusundan izin ver veya reddet düğmesine bastığında çağrılır
//burada izin durumlarını ele alınır(izin verildi ve reddedildi)
switch (requestCode){
case CAMERA_REQUESTED_CODE: {
//camera seçildiğinde önce izin alınmış mı diye kontrol eder
if (grantResults.length > 0 ){
boolean cameraAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
boolean writeStorageAccepted = grantResults[1] == PackageManager.PERMISSION_GRANTED;
if(cameraAccepted && writeStorageAccepted){
//izinler etkinleştirildi
pickFromCamera();
}
else{
//izinler reddedildi
Toast.makeText(getActivity(),"Please enable camera && storage permission",Toast.LENGTH_SHORT).show();
}
}
}
break;
//galeri seçildiğinde önce izin alınmış mı diye kontrol eder
case STORAGE_REQUESTED_CODE: {
if (grantResults.length > 0 ){
boolean cameraAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
boolean writeStorageAccepted = grantResults[1] == PackageManager.PERMISSION_GRANTED;
if(writeStorageAccepted){
//izinler etkinleştirildi
pickFromGallery();
}
else{
//izinler reddedildi
Toast.makeText(getActivity(),"Please enable storage permission",Toast.LENGTH_SHORT).show();
}
}
}
break;
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
//bu metot camera veya galeri den fotograf seçildikten sonra çağırılıyor
if (resultCode == RESULT_OK){
if (requestCode == IMAGE_PICK_GALLERY_CODE){
//resim geleriden seçildi, resmin uri'sini al
image_uri = data.getData();
uploadProfileCoverPhoto(image_uri);
}
if (requestCode == IMAGE_PICK_CAMERA_CODE){
//resim cameradan seçildi, resmin uri'sini al
uploadProfileCoverPhoto(image_uri);
}
}
super.onActivityResult(requestCode, resultCode, data);
}
//Editprofile dialog
private void showEditProfileDialog() {
// Profil resmi düzenle, kapak fotografı gösterme, isim düzenleme, açıklama düzenleme
//Seçenekleri dialogta gösterme
String options[] = {"Edit Profile Picture", "Edit Cover Photo", "Edit Name", "Edit Description"};
//alert dialog
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
//başlık
builder.setTitle("Choose Action");
//dialog itemlerini ayarlama
builder.setItems(options, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//dialog itemlere onClick özelliği ekleme
if (which == 0){
//profil düzenleme tıklandı
pd.setMessage("Updating Profile Picture");
//profil foto mu yoksa kapak foto mu konrol için
profileORCoverPhoto = "image"; // profil resmini değiştirirken aynı değerlerin atandığından emin ol
showImagePicDialog();
}
else if (which == 1){
//kapak düzenleme tıklandı
pd.setMessage("Updating Cover Picture");
//profil foto mu yoksa kapak foto mu konrol için
profileORCoverPhoto = "cover"; //kapak resmini değiştirirken aynı değerlerin atandığından emin ol
showImagePicDialog();
}
else if (which == 2){
//isim duzenleme tıklandı
pd.setMessage("Updating Name");
//veritabanında "name" güncellenmesi için motodun çağırılması
showNameDescUpdateDialog("name");
}
else if (which == 3){
//açıklama düzenleme tıklandı
pd.setMessage("Updating Description");
showNameDescUpdateDialog("desc");
}
}
});
//dialog oluşturme ve gösterme
builder.create().show();
}
private void showNameDescUpdateDialog(final String key) {
//key parametresi "name" ve "desc" değerlerini alıyor
//custom dialog
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Update "+key); //Update name or Update description..
//Dialog layoutunu ayarla
LinearLayout linearLayout = new LinearLayout(getActivity());
linearLayout.setOrientation(LinearLayout.VERTICAL);
linearLayout.setPadding(10,10,10,10);
//editText ekleme
final EditText editText = new EditText(getActivity());
editText.setHint("Enter "+ key);
linearLayout.addView(editText);
builder.setView(linearLayout);
//dialog'a update button ekle
builder.setPositiveButton("Update", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//input text from edit text
String value = editText.getText().toString().trim();
//kullanıcının bir şeyler girip girmediğini onayla
if (!TextUtils.isEmpty(value)){
pd.show();
HashMap<String, Object> result = new HashMap<>();
result.put(key, value);
databaseReference.child(user.getUid()).updateChildren(result)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
//güncellendi, dismiss progress
pd.dismiss();
Toast.makeText(getActivity(),"Updated...",Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
//error mesajı al ve göster, dismiss progress
pd.dismiss();
Toast.makeText(getActivity(),""+e.getMessage(),Toast.LENGTH_SHORT).show();
}
});
}
else {
Toast.makeText(getActivity(), "Please Enter "+key, Toast.LENGTH_SHORT).show();
}
}
});
//dialog'a cancel button ekle
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
//dialog'u oluştur ve göster
builder.create().show();
}
private void showImagePicDialog() {
//profil resmini cameradan ya da galeriden seçme seçenekleri ekleme
String options[] = {"Camera", "Gallery"};
//alert dialog
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
//başlık
builder.setTitle("Pick Image From");
//dialog itemlerini ayarlama
builder.setItems(options, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//dialog itemlere onClick özelliği ekleme
if (which == 0){
//camera tıklandı
// pd.setMessage("Updating Profile Picture");
//showImagePicDialog();
if (!checkCameraPermission()){
requestCameraPermission();
}
else{
pickFromCamera();
}
}
else if (which == 1){
//galeir tıklandı
//pd.setMessage("Updating Cover Picture");
if(!checkStoragePermission()){
requestStoragePermission();
}
else {
pickFromGallery();
}
}
}
});
//dialog oluşturme ve gösterme
builder.create().show();
}
private void uploadProfileCoverPhoto(final Uri uri) {
//Show progress dialog
pd.show();
//iki ayrı fonksiyon yerine profil resmi ve kapak resmi aynı fonksiyonda
//firabase storage'da depolanan resmin yolu ve adı
String filePathAndName = storagePath+ ""+ profileORCoverPhoto + "_"+ user.getUid();
StorageReference storageReference2nd = storageReference.child(filePathAndName);
storageReference2nd.putFile(uri)
.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
//resim depoya yüklendi, şimdi url'sini al ve kullanıcı veritabanında sakla
Task<Uri> uriTask = taskSnapshot.getStorage().getDownloadUrl();
while (!uriTask.isSuccessful());
Uri downloadUri = uriTask.getResult();
//resmin yüklenip yüklenmediğini ve url'nin alındığını kontrol edin
if (uriTask.isSuccessful()){
//resim yüklendi
//kullanıcı veritabanına url'i ekle/güncelle
HashMap<String, Object> results = new HashMap<>();
//ilk parametre profileOrCoverPhote image veya cover değerlerine sahip
//ikinci parametre firebase storage'da depolanan resmin url
results.put(profileORCoverPhoto, downloadUri.toString());
databaseReference.child(user.getUid()).updateChildren(results)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
pd.dismiss();
Toast.makeText(getActivity(), "Image Updated...", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
pd.dismiss();
Toast.makeText(getActivity(), "Error Updating Image...", Toast.LENGTH_SHORT).show();
}
});
}
else {
//error
pd.dismiss();
Toast.makeText(getActivity(), "Some error occured", Toast.LENGTH_SHORT).show();
}
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
//bazı errorlar var, errorları al ve error mesajı göster, dissmis dialog
pd.dismiss();
Toast.makeText(getActivity(), e.getMessage(),Toast.LENGTH_SHORT).show();
}
});
}
private void pickFromCamera() {
//cihaz kamerasından görüntü alma
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, "Temp Pic");
values.put(MediaStore.Images.Media.DESCRIPTION, "Temp Description");
//resim uri'si
image_uri = getActivity().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
//camera başlatılması
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, image_uri);
startActivityForResult(cameraIntent, IMAGE_PICK_CAMERA_CODE);
}
private void pickFromGallery() {
//galeriden resim seçme
Intent galleryIntent = new Intent(Intent.ACTION_PICK);
galleryIntent.setType("image/*");
startActivityForResult(galleryIntent, IMAGE_PICK_GALLERY_CODE);
}
}
我的 AndroidManifes.xml 是
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.gamze.pawsbook">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.CAMERA"
android:maxSdkVersion="29" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".LoginActivity"></activity>
<activity android:name=".DashboardActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".RegisterActivity" />
<activity android:name=".MainActivity"></activity>
</application>
</manifest>
我的 build.gradle(module:app)
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
android {
compileSdkVersion 29
defaultConfig {
applicationId "com.gamze.pawsbook"
minSdkVersion 22
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.google.android.material:material:1.1.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
// add the Firebase SDK for Google Analytics
implementation 'com.google.firebase:firebase-analytics:17.2.2'
//Firebase authentication library
implementation 'com.google.firebase:firebase-auth:19.3.2'
implementation 'com.google.android.gms:play-services-auth:18.1.0'
//google sign in library
implementation 'com.google.android.gms:play-services-auth:18.1.0'
//Firebase Realtime Database
implementation 'com.google.firebase:firebase-database:19.3.1'
//Firebase Storage
implementation 'com.google.firebase:firebase-storage:19.1.1'
//Picasso library (resimleri eklemek için)
implementation 'com.squareup.picasso:picasso:2.71828'
}
解决方案
ByteArrayOutputStream
我建议在将 Bitmap 转换为not后尝试保存它URI
。
您可以按如下方式获取用户选择的位图 -
....
Bitmap newImage; //make it a global variable
.....
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != RESULT_CANCELED) {
switch (requestCode) {
case 0: //Image from Camera
if (resultCode == RESULT_OK && data != null) {
newImage = (Bitmap) data.getExtras().get("data");
userImage.setImageBitmap(newImage);
newImageSet = true;
}
break;
case 1: //Image from gallery/user device
if (resultCode == RESULT_OK && data != null) {
Uri selectedImage = data.getData();
String[] filePathColumn = {MediaStore.Images.Media.DATA};
if (selectedImage != null) {
Cursor cursor = getActivity().getContentResolver().query(selectedImage,
filePathColumn, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
newImage = BitmapFactory.decodeFile(picturePath);
userImage.setImageBitmap(newImage);
cursor.close();
}
}
}
break;
}
}
}
获得新图像 bitmp 后,您可以将 Bitmap 放入 Firstore。
public void saveImageToFirbase(){
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
newImage.compress(Bitmap.CompressFormat.JPEG, 40, byteArrayOutputStream);
StorageReference imgReference = FirebaseStorage.getInstance().getReference()
.child("User Profile Image")
.child(FirebaseAuth.getInstance().getCurrentUser().getUid() + ".jpeg");
//adjust imgReference according to your database structure
imgReference.putBytes(byteArrayOutputStream.toByteArray())
.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
getDownloadUrl(imgReference);
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.e(TAG, "onFailure: ", e.getCause());
}
});
}
这里Bitmap.CompressFormat.JPEG, 40
整数值将是压缩级别。
方法 getgetDownloadUrl() -
private void getDownloadUrl(StorageReference storageReference) {
storageReference.getDownloadUrl()
.addOnSuccessListener(new OnSuccessListener<Uri>() {
@Override
public void onSuccess(Uri uri) {
setUserProfileUrl(uri);
}
});
}
至少您可以更新用户的个人资料并设置 ImageUrl -
private void setUserProfileUrl(Uri userProfileUrl) {
FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
UserProfileChangeRequest userProfileChangeRequest = new UserProfileChangeRequest.Builder()
.setPhotoUri(userProfileUrl).build();
firebaseUser.updateProfile(userProfileChangeRequest)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
//some more update in your view
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.e(TAG, "onFailure: ", e.getCause());
}
});
}
快乐编码!
推荐阅读
- javascript - 表单字段名称的动态编号
- javac - 是否可以将 Java 编译器嵌入到应用程序中?
- c++ - pow() 函数给出错误
- c# - Outlook 拒绝来自 CryptProtectData() 的密码
- angularjs - AngularJS - 如何编写包含 momentjs 库的单元测试?
- c# - 使一个简单的 C# 静态函数成为 WebAssembly
- html - 动态生成嵌入在 VBA 电子邮件生成中的 HTML 表
- python - 最接近用户输入的数字
- java - 如何在 JPA 中使用 TypedQuery 更改顺序
- android - 相对布局中的 layout_below 不会显示