【问题标题】:AsyncTask Image Compression - FATAL EXCEPTION: AsyncTask #3 (Upload to Firebase Storage Later))AsyncTask 图像压缩 - 致命例外:AsyncTask #3(稍后上传到 Firebase 存储))
【发布时间】:2018-10-07 13:53:33
【问题描述】:

我正在尝试使用此类在后台线程中压缩图像...

public class BackgroundImageResize extends AsyncTask<Uri, Integer, byte[]>{

    Bitmap mBitmap;

    public BackgroundImageResize(Bitmap bitmap) {
        if(bitmap != null){
            this.mBitmap = bitmap;
        }
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        Toast.makeText(NextActivity.this, "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(NextActivity.this.getContentResolver(), params[0]);
            }catch (IOException e){
                Log.e(TAG, "doInBackground: IOException: " + e.getMessage());
            }
            catch (NullPointerException e)
            {

            }
        }
        byte[] bytes = null;
        bytes = getBytesFromBitmap(mBitmap, 100);
        return bytes;
    }

    @Override
    protected void onPostExecute(byte[] bytes) {
        super.onPostExecute(bytes);
        mUploadBytes = bytes;

        //execute the upload task


    }
}

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

将位图传递给构造函数,如

BackgroundImageResize backgroundImageResize = new BackgroundImageResize(bitmap);

并像在onClickListener中调用execute()方法

 @Override
        public void onClick(View v) {
            Log.d(TAG, "onClick: navigating to the final share screen.");

            //Compress the image

             backgroundImageResize.execute();

我收到了这个 FATAL EXCEPTION 错误

4-27 00:10:01.318 17091-18093/manika.aditya.ekayana E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #3
                                                                   Process: manika.aditya.ekayana, PID: 17091
                                                                   java.lang.RuntimeException: An error occurred while executing doInBackground()
                                                                       at android.os.AsyncTask$3.done(AsyncTask.java:325)
                                                                       at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
                                                                       at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
                                                                       at java.util.concurrent.FutureTask.run(FutureTask.java:242)
                                                                       at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
                                                                       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
                                                                       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
                                                                       at java.lang.Thread.run(Thread.java:761)
                                                                    Caused by: java.lang.ArrayIndexOutOfBoundsException: length=0; index=0
                                                                       at manika.aditya.ekayana.Share.NextActivity$BackgroundImageResize.doInBackground(NextActivity.java:158)
                                                                       at manika.aditya.ekayana.Share.NextActivity$BackgroundImageResize.doInBackground(NextActivity.java:135)
                                                                       at android.os.AsyncTask$2.call(AsyncTask.java:305)

每当我运行应用程序并单击 textView 我不明白是什么原因造成的......

我必须稍后将压缩图像上传到 Firebase 存储

这是上传方式,以防万一

public void uploadNewPhoto(String photoType, final String caption,final int count, final String imgUrl,
                       Bitmap bm){
Log.d(TAG, "uploadNewPhoto: attempting to uplaod new photo.");

FilePaths filePaths = new FilePaths();
//case1) new photo
if(photoType.equals(mContext.getString(R.string.new_photo))){
    Log.d(TAG, "uploadNewPhoto: uploading NEW photo.");

    String user_id = FirebaseAuth.getInstance().getCurrentUser().getUid();
    StorageReference storageReference = mStorageReference
            .child(filePaths.FIREBASE_IMAGE_STORAGE + "/" + user_id + "/photo" + (count + 1));

    //convert image url to bitmap
    if(bm == null){
        bm = ImageManager.getBitmap(imgUrl);
    }

    byte[] bytes = ImageManager.getBytesFromBitmap(bm, 90);


    UploadTask uploadTask = null;
    uploadTask = storageReference.putBytes(bytes);

    uploadTask.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
        @Override
        public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
            Uri firebaseUrl = taskSnapshot.getDownloadUrl();

            Toast.makeText(mContext, "photo upload success", Toast.LENGTH_SHORT).show();

            //add the new photo to 'photos' node and 'user_photos' node
            addPhotoToDatabase(caption, firebaseUrl.toString());

            //navigate to the main feed so the user can see their photo
            Intent intent = new Intent(mContext, HomeActivity.class);
            mContext.startActivity(intent);
        }
    }).addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            Log.d(TAG, "onFailure: Photo upload failed.");
            Toast.makeText(mContext, "Photo upload failed ", Toast.LENGTH_SHORT).show();
        }
    }).addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
        @Override
        public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
            double progress = (100 * taskSnapshot.getBytesTransferred()) / taskSnapshot.getTotalByteCount();

            if(progress - 15 > mPhotoUploadProgress){
                Toast.makeText(mContext, "photo upload progress: " + String.format("%.0f", progress) + "%", Toast.LENGTH_SHORT).show();
                mPhotoUploadProgress = progress;
            }

            Log.d(TAG, "onProgress: upload progress: " + progress + "% done");
        }
    });

我知道答案可能很明显,但我是初学者......提前谢谢你:)

顺便说一下,这就是我调用上传方法的方式

                //upload the image to firebase

            Toast.makeText(NextActivity.this, "Attempting to upload new photo", Toast.LENGTH_SHORT).show();
            String caption = mCaption.getText().toString();

            if(intent.hasExtra(getString(R.string.selected_image))){
                imgUrl = intent.getStringExtra(getString(R.string.selected_image));
                mFirebaseMethods.uploadNewPhoto(getString(R.string.new_photo), caption, imageCount, imgUrl,null);
            }
            else if(intent.hasExtra(getString(R.string.selected_bitmap))){
                bitmap = (Bitmap) intent.getParcelableExtra(getString(R.string.selected_bitmap));
                mFirebaseMethods.uploadNewPhoto(getString(R.string.new_photo), caption, imageCount, null,bitmap);
            }

在onClickViewListener中

:P

【问题讨论】:

    标签: android firebase android-asynctask firebase-storage image-compression


    【解决方案1】:

    根据您的日志,问题是

    java.lang.ArrayIndexOutOfBoundsException: length=0; index=0
    

    我相信,这是由param[0] 引起的

    mBitmap = MediaStore.Images.Media.getBitmap(NextActivity.this.getContentResolver(), params[0]);
    

    params[] 必须是null,因为在onClick() 中调用backgroundImageResize.execute() 时不带参数,该参数将传递给doInBackground() 并存储在param[] 中。

    作为解决方案,您只需将 Uri 传递给您的 onClick() 中的 backgroundImageResize.execute(),如下所示:

    @Override
    public void onClick(View v) {
        ...
        backgroundImageResize.execute(myUri);
        ...
    }
    

    另一种方法是通过像这样在doInBackground() 中捕获ArrayIndexOutOfBoundsException 来避免您的应用崩溃:

    if(mBitmap == null){
        try{
            mBitmap = MediaStore.Images.Media.getBitmap(NextActivity.this.getContentResolver(), params[0]);
        }catch (IOException e){
            Log.e(TAG, "doInBackground: IOException: " + e.getMessage());
        }
        catch (NullPointerException e) {}
        catch (ArrayIndexOutOfBoundsExeption aioobe) {}
    }
    

    【讨论】:

    • 最后一个烦人的问题:PI 在 backgroundImageResize.execute(imageUri); 中将图像 URI 作为参数传递,但现在我收到此错误 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getByteCount() on a null object reference,因为我正在使用 getByteCount() 函数来记录图像大小,压缩前后Log.d(TAG, "size before compression " + mBitmap.getByteCount() / 1000000); bytes = getBytesFromBitmap(mBitmap, 100); Log.d(TAG, "size after compression " + bytes.length / 1000000);
    • 好像mBitmapnull。我的猜测是,Uri 不正确,因此MediaStore.Images.Media.getBitmap() 返回null。为避免您的应用程序崩溃,您可以将 bytes = getBytesFromBitmap(mBitmap, 100); 放在 try-catch-block 或 if 语句中,您可以在其中检查 mBitmap 是否为 null
    • 这就是我检索 Uri imgUrl = intent.getStringExtra(getString(R.string.selected_image)); imageUri = Uri.parse(imgUrl) ; 的方式,不要担心仅用于传递图像标题的 getStringExtra()。这是正确的方法吗?在整个项目中,我一直在使用 getString() 方法检索 Url,没有出现任何问题。在此先感谢,你太棒了:)
    • 是的,你可以这样做。但我的意思是:你正在传递的 uri 是否正确。我的意思是,在 url 指定的位置真的存在图像文件吗?你应该检查一下。
    • 另一件事:以下问题与主题问题无关,不应在评论中提出。你最好在 stackoverflow 上问一个新的问题。
    猜你喜欢
    • 2018-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-31
    • 2017-03-15
    • 2021-01-03
    • 1970-01-01
    • 2022-01-18
    相关资源
    最近更新 更多