android - 对于同一个位图,位图有时保存为黑色图像

标签 android bitmap qr-code universal-image-loader android-bitmap

我知道这是一个常见问题,但我尝试了不同的建议,但仍然没有解决方案。

我的问题是位图显示正确,但有时它保存为黑色位图,而其他时候保存正确。

谁能看到我做了什么并告诉我哪里可能出错?

我已经查看了大多数其他 StackOverflow 问题。

下面是我的代码,将剪贴板文本编码成二维码,并尝试保存生成的二维码。

谢谢!

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.text.ClipboardManager;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;

import java.io.File;
import java.io.FileOutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

//import android.content.ClipboardManager;

public class BarcodeWriter extends AppCompatActivity {
    ImageLoader imgLoader;
    ImageView qrImg;
    String copiedStr;
    TextView qrTxt;
    ClipboardManager clipboard;

    String BASE_QR_URL = "http://chart.apis.google.com/chart?cht=qr&chs=400x400&chld=M&choe=UTF-8&chl=";
    String fullUrl = BASE_QR_URL;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.barcode_writer);

        DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
                .cacheInMemory(true)
                .cacheOnDisk(true)
                .build();

        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
                .defaultDisplayImageOptions(defaultOptions)
                .build();
        imgLoader = ImageLoader.getInstance(); // Do it on Application start
        imgLoader.init(config);

        qrImg = (ImageView)findViewById(R.id.qrImg);
        qrTxt = (TextView)findViewById(R.id.qrTxt);

        clipboard = (ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE);

        /*
         * clipboard.getText() is now deprecated. But I am going to use it here
         * because the new way of doing the same thing only works on API lvl 11+
         * Since I want this application to support API lvl 4+ we have to use
         * the old method.
         */
        CharSequence clipTxt = clipboard.getText();

        //This is the new, non-deprecated way of getting text from the Clipboard.
        //CharSequence clipTxt = clipboard.getPrimaryClip().getItemAt(0).getText();


        //If the clipboard has text, and it is more than 0 characters.
        if((null != clipTxt) && (clipTxt.length() > 0)){
            try {
                qrTxt.setText(clipTxt);
                copiedStr = clipTxt.toString();
                fullUrl += URLEncoder.encode(copiedStr, "UTF-8");
                //imgLoader.displayImage(fullUrl, qrImg);


                ImageLoader.getInstance().displayImage(fullUrl, qrImg, defaultOptions); // Incoming options will be used

                qrImg.setDrawingCacheEnabled(true);

                qrImg.measure(View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY),
                        View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY));
                qrImg.layout(0, 0, qrImg.getMeasuredWidth(), qrImg.getMeasuredHeight());

                qrImg.buildDrawingCache();
                Bitmap bm = Bitmap.createBitmap(qrImg.getDrawingCache());
                qrImg.setDrawingCacheEnabled(false); // clear drawing cache


                try {

                    String root = Environment.getExternalStorageDirectory().toString();
                    File myDir = new File(root + "/DCIM/QR codes");
                    myDir.mkdirs();


                    String fname = clipTxt+".png";
                    File file = new File (myDir, fname);

                    if (file.exists ()) file.delete ();
                    try {
                        FileOutputStream out = new FileOutputStream(file);
                        bm.compress(Bitmap.CompressFormat.PNG, 100, out);
                        Toast.makeText(BarcodeWriter.this, "Image Saved", Toast.LENGTH_SHORT).show();
                        out.flush();
                        out.close();

                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
                    Uri contentUri = Uri.fromFile(file);
                    mediaScanIntent.setData(contentUri);
                    getApplicationContext().sendBroadcast(mediaScanIntent);

                    Toast.makeText(this,"QR Code showing "+clipTxt,Toast.LENGTH_SHORT).show();
                } catch (Exception e) {
                    Toast.makeText(this, "Error occurred. Please try again later.",
                            Toast.LENGTH_SHORT).show();
                }



            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }else{ //If no text display a dialog.

            Toast.makeText(this,"No text in clipboard",Toast.LENGTH_SHORT).show();
        }
    }
}

最佳答案

您的代码似乎没问题,我唯一看到的是您在调用 displayImage 后立即使用 Universal Image Loader 从外部 URL 获取位图。因此,由于网络延迟,有时您的 ImageView 仍然没有完整的图像,这可能会使您的位图保存为黑色。

请尝试将所有代码移动到 onLoadingComplete 中的 ImageLoader.getInstance().displayImage 中,如下所示:

    ImageLoader.getInstance().displayImage(fullUrl, qrImg, defaultOptions,  new SimpleImageLoadingListener()
    {        

        @Override
        public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
             ImageLoader.getInstance().displayImage(fullUrl, qrImg, defaultOptions,null);
             qrImg.setDrawingCacheEnabled(true);
             ...
             catch (Exception e) {
                Toast.makeText(this, "Error occurred. Please try again  later.",
                        Toast.LENGTH_SHORT).show();
            }

        }
    });

希望对您有所帮助!!

关于android - 对于同一个位图,位图有时保存为黑色图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36243472/

相关文章:

android - 具有旧样式和不同颜色的 TimePickerDialog

c# - 将图像绘制到更大的位图

laravel - Laravel 中的二维码

android - Yandex MapKit 3.0 崩溃

android - 单击其中一个按钮(不是内容区域)后如何关闭大 View 通知

java - 覆盖方法中的变量名不正确

android - 使用 Picasso 和 OkHttp 更新/更改缓存位图

java - 向位图添加虚线边框

laravel-5 - 最佳条形码以及如何/从什么生成条形码,以及如何以最佳方式存储它?

java - 如何为 Android 应用程序生成二维码?