图片上传时Firebase NullPointerException

问题描述 投票:0回答:1

在我的firebase应用程序中,我有一个无法解决的问题。

在我的AccountFragment我尝试上传用户个人资料图片 - 选择图像后,应用程序崩溃。请帮我解决这个问题

我已经在这几天了,我真的迷失了。

当我尝试上传图片时,应用程序仅崩溃,当我尝试更新姓名,电话号码或电子邮件时 - 一切正常

package com.company.walt.fragments;

public class AccountFragment extends BaseFragment implements
        ChangePhotoDialog.OnPhotoReceivedListener {

    // Statics
    private static final String TAG = "AccountFragment";

    private static final int REQUEST_CODE = 1234;
    private static final double MB_THRESHHOLD = 5.0;
    private static final double MB = 1000000.0;

    // Widgets
    private ImageView mProfileImage;
    private EditText mName;
    private EditText mEmail;
    private EditText mPhone;
    private EditText mConfirm;
    private Button mUpdateBtn;

    // Vars
    private boolean mStoragePermissions;
    private Uri mSelectedImageUri;
    private Bitmap mSelectedImageBitmap;
    private byte[] mBytes;
    private double progress;

    public AccountFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_account, container, false);

        mProfileImage = (ImageView)view.findViewById(R.id.user_img);
        mName = (EditText) view.findViewById(R.id.input_name);
        mEmail = (EditText) view.findViewById(R.id.input_email);
        mPhone = (EditText) view.findViewById(R.id.input_phone);
        mConfirm = (EditText) view.findViewById(R.id.input_confirm);
        mUpdateBtn = (Button) view.findViewById(R.id.btn_update);

        setupFirebaseAuth();

        updateInformation();

        hideSoftKeyboard();

        return view;
    }

    private void updateInformation(){

        mProfileImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                if(mStoragePermissions){
                    ChangePhotoDialog dialog = new ChangePhotoDialog();
                    dialog.show(getChildFragmentManager(), "ChangePhotoDialog");

                }else{
                    verifyStoragePermissions();
                }

            }
        });

        mUpdateBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                Log.d(TAG, "onClick: Attempting to save settings");

                DatabaseReference reference = FirebaseDatabase.getInstance().getReference();

                // If user only wants to update name
                if (!isEmpty(mName.getText().toString())) {

                    reference.child(getString(R.string.dbnode_users))
                            .child(FirebaseAuth.getInstance().getCurrentUser().getUid())
                            .child(getString(R.string.field_name))
                            .setValue(mName.getText().toString());

                    Toast.makeText(getActivity(), "Your name have been updated", Toast.LENGTH_SHORT).show();

                }

                // If user only wants to update phone
                if (!isEmpty(mPhone.getText().toString())) {

                    reference.child(getString(R.string.dbnode_users))
                            .child(FirebaseAuth.getInstance().getCurrentUser().getUid())
                            .child(getString(R.string.field_phone))
                            .setValue(mPhone.getText().toString());

                    Toast.makeText(getActivity(), "Your phone have been updated", Toast.LENGTH_SHORT).show();

                }

                // If user only wants to update email
                if (!isEmpty(mEmail.getText().toString())
                        && !isEmpty(mConfirm.getText().toString())) {

                    updateUserEmailOnly();

                }
                if (!isEmpty(mEmail.getText().toString())
                        && isEmpty(mConfirm.getText().toString())) {
                    Toast.makeText(getActivity(), "You must enter password to change email", Toast.LENGTH_SHORT).show();
                }
                else if (isEmpty(mEmail.getText().toString())
                        && !isEmpty(mConfirm.getText().toString())) {

                    Toast.makeText(getActivity(), "You only entered password, nothing will happen", Toast.LENGTH_SHORT).show();

                }


                /*
                ------ Upload the New Photo -----
                 */
                if(mSelectedImageUri != null){
                    uploadNewPhoto(mSelectedImageUri);
                }else if(mSelectedImageBitmap  != null){
                    uploadNewPhoto(mSelectedImageBitmap);
                }


            }

        });

    }

    /**
     * Uploads a new profile photo to Firebase Storage using a @param ***imageUri***
     * @param imageUri
     */
    public void uploadNewPhoto(Uri imageUri){
        /*
            upload a new profile photo to firebase storage
         */
        Log.d(TAG, "uploadNewPhoto: uploading new profile photo to firebase storage.");

        //Only accept image sizes that are compressed to under 5MB. If thats not possible
        //then do not allow image to be uploaded
        BackgroundImageResize resize = new BackgroundImageResize(null);
        resize.execute(imageUri);
    }

    /**
     * Uploads a new profile photo to Firebase Storage using a @param ***imageBitmap***
     * @param imageBitmap
     */
    public void uploadNewPhoto(Bitmap imageBitmap){
        /*
            upload a new profile photo to firebase storage
         */
        Log.d(TAG, "uploadNewPhoto: uploading new profile photo to firebase storage.");

        //Only accept image sizes that are compressed to under 5MB. If thats not possible
        //then do not allow image to be uploaded
        BackgroundImageResize resize = new BackgroundImageResize(imageBitmap);
        Uri uri = null;
        resize.execute(uri);
    }

    /**
     * 1) doinBackground takes an imageUri and returns the byte array after compression
     * 2) onPostExecute will print the % compression to the log once finished
     */
    public class BackgroundImageResize extends AsyncTask<Uri, Integer, byte[]> {

        Bitmap mBitmap;
        public BackgroundImageResize(Bitmap bm) {
            if(bm != null){
                mBitmap = bm;
            }
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            showProgress();
            Toast.makeText(getActivity(), "compressing image", Toast.LENGTH_SHORT).show();
        }

        @Override
        protected byte[] doInBackground(Uri... params ) {
            Log.d(TAG, "doInBackground: started.");

            if(mBitmap == null){

                try {
                    mBitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), params[0]);
                    Log.d(TAG, "doInBackground: bitmap size: megabytes: " + mBitmap.getByteCount()/MB + " MB");
                } catch (IOException e) {
                    Log.e(TAG, "doInBackground: IOException: ", e.getCause());
                }
            }

            byte[] bytes = null;
            for (int i = 1; i < 11; i++){
                if(i == 10){
                    Toast.makeText(getActivity(), "That image is too large.", Toast.LENGTH_SHORT).show();
                    break;
                }
                bytes = getBytesFromBitmap(mBitmap,100/i);
                Log.d(TAG, "doInBackground: megabytes: (" + (11-i) + "0%) "  + bytes.length/MB + " MB");
                if(bytes.length/MB  < MB_THRESHHOLD){
                    return bytes;
                }
            }
            return bytes;
        }


        @Override
        protected void onPostExecute(byte[] bytes) {
            super.onPostExecute(bytes);
            hideProgress();
            mBytes = bytes;
            //execute the upload
            executeUploadTask();
        }
    }

    // convert from bitmap to byte array
    public static byte[] getBytesFromBitmap(Bitmap bitmap, int quality) {
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, quality, stream);
        return stream.toByteArray();
    }

    private void executeUploadTask(){
        showProgress();
        FilePaths filePaths = new FilePaths();

        //specify where the photo will be stored
        final StorageReference storageReference = FirebaseStorage.getInstance().getReference()
                .child(filePaths.FIREBASE_USER_IMAGE_STORAGE + "/" + FirebaseAuth.getInstance().getCurrentUser().getUid()
                        + "/profile_image"); //just replace the old image with the new one

        if(mBytes.length/MB < MB_THRESHHOLD) {

            // Create file metadata including the content type
            StorageMetadata metadata = new StorageMetadata.Builder()
                    .setContentType("image/jpg")
                    .setContentLanguage("en") //see nodes below
                    /*
                    Make sure to use proper language code ("English" will cause a crash)
                    I actually submitted this as a bug to the Firebase github page so it might be
                    fixed by the time you watch this video. You can check it out at https://github.com/firebase/quickstart-unity/issues/116
                     */
                    .setCustomMetadata("Mitch's special meta data", "JK nothing special here")
                    .setCustomMetadata("location", "Iceland")
                    .build();
            //if the image size is valid then we can submit to database
            UploadTask uploadTask = null;
            uploadTask = storageReference.putBytes(mBytes, metadata);
            //uploadTask = storageReference.putBytes(mBytes); //without metadata


            uploadTask.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                @Override
                public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                    //Now insert the download url into the firebase database
                    Uri firebaseURL = taskSnapshot.getDownloadUrl();
                    Toast.makeText(getActivity(), "Upload Success", Toast.LENGTH_SHORT).show();
                    Log.d(TAG, "onSuccess: firebase download url : " + firebaseURL.toString());
                    FirebaseDatabase.getInstance().getReference()
                            .child(getString(R.string.dbnode_users))
                            .child(FirebaseAuth.getInstance().getCurrentUser().getUid())
                            .child(getString(R.string.field_profile_image))
                            .setValue(firebaseURL.toString());

                    hideProgress();
                }
            }).addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception exception) {
                    Toast.makeText(getActivity(), "could not upload photo", Toast.LENGTH_SHORT).show();

                    hideProgress();

                }
            }).addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
                @Override
                public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
                    double currentProgress = (100 * taskSnapshot.getBytesTransferred()) / taskSnapshot.getTotalByteCount();
                    if(currentProgress > (progress + 15)){
                        progress = (100 * taskSnapshot.getBytesTransferred()) / taskSnapshot.getTotalByteCount();
                        Log.d(TAG, "onProgress: Upload is " + progress + "% done");
                        Toast.makeText(getActivity(), progress + "%", Toast.LENGTH_SHORT).show();
                    }

                }
            })
            ;
        }else{
            Toast.makeText(getActivity(), "Image is too Large", Toast.LENGTH_SHORT).show();
        }

    }

    /**
     * Generalized method for asking permission. Can pass any array of permissions
     */
    public void verifyStoragePermissions(){
        Log.d(TAG, "verifyPermissions: asking user for permissions.");
        String[] permissions = {
                android.Manifest.permission.READ_EXTERNAL_STORAGE,
                android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.CAMERA};

        if (ContextCompat.checkSelfPermission(this.getActivity(),
                permissions[0] ) == PackageManager.PERMISSION_GRANTED
                && ContextCompat.checkSelfPermission(this.getActivity(),
                permissions[1] ) == PackageManager.PERMISSION_GRANTED
                && ContextCompat.checkSelfPermission(this.getActivity(),
                permissions[2] ) == PackageManager.PERMISSION_GRANTED) {

            mStoragePermissions = true;

        }
        else {

            ActivityCompat.requestPermissions(getActivity(), permissions, REQUEST_CODE);
        }

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        Log.d(TAG, "onRequestPermissionsResult: requestCode: " + requestCode);
        switch(requestCode){
            case REQUEST_CODE:
                if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
                    Log.d(TAG, "onRequestPermissionsResult: User has allowed permission to access: " + permissions[0]);

                }
                break;
        }
    }

    @Override
    public void getImagePath(Uri imagePath) {
        if( !imagePath.toString().equals("")){
            mSelectedImageBitmap = null;
            mSelectedImageUri = imagePath;
            Log.d(TAG, "getImagePath: got the image uri: " + mSelectedImageUri);
            ImageLoader.getInstance().displayImage(imagePath.toString(), mProfileImage);
        }

    }

    @Override
    public void getImageBitmap(Bitmap bitmap) {
        if(bitmap != null){
            mSelectedImageUri = null;
            mSelectedImageBitmap = bitmap;
            Log.d(TAG, "getImageBitmap: got the image bitmap: " + mSelectedImageBitmap);
            mProfileImage.setImageBitmap(bitmap);
        }
    }

    /*
    * **********************************************************************************************
    * USER OPTION METHODS
    * */

    /**
     * Update Email Only
     */
    private void updateUserEmailOnly() {

        showProgress();

        AuthCredential credential = EmailAuthProvider
                .getCredential(FirebaseAuth.getInstance().getCurrentUser().getEmail(), mConfirm.getText().toString());

        FirebaseAuth.getInstance().getCurrentUser().reauthenticate(credential)
                .addOnCompleteListener(new OnCompleteListener<Void>() {
                    @Override
                    public void onComplete(@NonNull Task<Void> task) {

                        if (task.isSuccessful()) {

                            Log.d(TAG, "onComplete: reauthenticate success.");

                            ///////////////////now check to see if the email is not already present in the database
                            FirebaseAuth.getInstance().fetchProvidersForEmail(mEmail.getText().toString()).addOnCompleteListener(
                                    new OnCompleteListener<ProviderQueryResult>() {
                                        @Override
                                        public void onComplete(@NonNull Task<ProviderQueryResult> task) {

                                            if (task.isSuccessful()) {

                                                ///////// getProviders().size() will return size 1 if email ID is in use.
                                                Log.d(TAG, "onComplete: RESULT: " + task.getResult().getProviders().size());

                                                if (task.getResult().getProviders().size() == 1) {
                                                    Log.d(TAG, "onComplete: That email is already in use.");

                                                    hideProgress();
                                                    Toast.makeText(getActivity(), "That email is already in use", Toast.LENGTH_SHORT).show();
                                                } else {
                                                    Log.d(TAG, "onComplete: That email is available.");

                                                    /////////////////////add new email
                                                    FirebaseAuth.getInstance().getCurrentUser().updateEmail(mEmail.getText().toString())
                                                            .addOnCompleteListener(new OnCompleteListener<Void>() {
                                                                @Override
                                                                public void onComplete(@NonNull Task<Void> task) {
                                                                    if (task.isSuccessful()) {
                                                                        Log.d(TAG, "onComplete: User email address updated.");
                                                                        Toast.makeText(getActivity(), "Updated email", Toast.LENGTH_SHORT).show();
                                                                        sendVerificationEmail();
                                                                        FirebaseAuth.getInstance().signOut();
                                                                    } else {
                                                                        Log.d(TAG, "onComplete: Could not update email.");
                                                                        Toast.makeText(getActivity(), "unable to update email", Toast.LENGTH_SHORT).show();
                                                                    }

                                                                    hideProgress();
                                                                }
                                                            })
                                                            .addOnFailureListener(new OnFailureListener() {
                                                                @Override
                                                                public void onFailure(@NonNull Exception e) {
                                                                    hideProgress();
                                                                    Toast.makeText(getActivity(), "unable to update email", Toast.LENGTH_SHORT).show();
                                                                }
                                                            });
                                                }
                                            }

                                        }
                                    })
                                    .addOnFailureListener(new OnFailureListener() {
                                        @Override
                                        public void onFailure(@NonNull Exception e) {
                                            hideProgress();
                                            Toast.makeText(getActivity(), "“unable to update email”", Toast.LENGTH_SHORT).show();
                                        }
                                    });

                        } else {
                            Log.d(TAG, "onComplete: Incorrect Password");
                            Toast.makeText(getActivity(), "Incorrect Password", Toast.LENGTH_SHORT).show();
                            hideProgress();
                        }
                    }

                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        hideProgress();
                        Toast.makeText(getActivity(), "“unable to update email”", Toast.LENGTH_SHORT).show();
                    }
                });
    }

    /**
     * sends an email verification link to the user
     */
    public void sendVerificationEmail() {

        FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();

        if (user != null) {
            user.sendEmailVerification()
                    .addOnCompleteListener(new OnCompleteListener<Void>() {
                        @Override
                        public void onComplete(@NonNull Task<Void> task) {
                            if (task.isSuccessful()) {
                                Toast.makeText(getActivity(), "Sent Verification Email", Toast.LENGTH_SHORT).show();
                            } else {
                                Toast.makeText(getActivity(), "Couldn't Verification Send Email", Toast.LENGTH_SHORT).show();
                            }
                        }
                    });
        }

    }

    /**
     * Return true if the @param is null
     * @param string
     * @return
     */
    private boolean isEmpty(String string) {
        return string.equals("");
    }

    /*
    * **********************************************************************************************
    * INHERITED METHODS
    * */

    /**
     * Display progressbar
     */
    protected void showProgress() {
        if (getActivity() instanceof IProgressDisplay) {
            ((IProgressDisplay) getActivity()).showProgress();
        }
    }

    /**
     * Hide progressbar
     */
    protected void hideProgress() {
        if (getActivity() instanceof IProgressDisplay) {
            ((IProgressDisplay) getActivity()).hideProgress();
        }
    }

    /**
     * Hide softKeyboard
     */
    protected void hideSoftKeyboard() {
        if (getActivity() instanceof ISoftKeyboard) {
            ((ISoftKeyboard) getActivity()).hideSoftKeyboard();
        }
    }

    /**
     * Firebase Auth
     */
    protected void setupFirebaseAuth() {
        if (getActivity() instanceof IFirebaseAuth) {
            ((IFirebaseAuth) getActivity()).setupFirebaseAuth();
        }
    }
}

这是LogCat

01-02 20:34:41.590 16223-16223/com.company.walt E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.company.walt, PID: 16223
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=73888, result=-1, data=Intent { dat=content://com.android.providers.media.documents/document/image:672 flg=0x1 }} to activity {com.company.walt/com.company.walt.activities.MainActivity}: java.lang.NullPointerException: Attempt to invoke interface method 'void com.company.walt.Dialogs.ChangePhotoDialog$OnPhotoReceivedListener.getImagePath(android.net.Uri)' on a null object reference
at android.app.ActivityThread.deliverResults(ActivityThread.java:4528)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4571)
at android.app.ActivityThread.-wrap19(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1744)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6809)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'void com.company.walt.Dialogs.ChangePhotoDialog$OnPhotoReceivedListener.getImagePath(android.net.Uri)' on a null object reference
at com.company.walt.Dialogs.ChangePhotoDialog.onActivityResult(ChangePhotoDialog.java:78)
at android.support.v4.app.FragmentActivity.onActivityResult(FragmentActivity.java:151)
at android.app.Activity.dispatchActivityResult(Activity.java:7267)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4524)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4571) 
at android.app.ActivityThread.-wrap19(Unknown Source:0) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1744) 
at android.os.Looper.loop(Looper.java:164) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767) 
01-02 20:34:41.591 468-468/? W/auditd: type=1400 "[email protected]""mem""debugfs"
java android firebase
1个回答
0
投票

您正在收到该错误,因为您正在调用未初始化对象上的方法,这就是您获得NullPointerException的原因。要解决此问题,您只需要初始化调用getImagePath()方法的变量。还要确保每次使用对象检查nullity

© www.soinside.com 2019 - 2024. All rights reserved.