【问题标题】:Null pointer exception when scaling down bitmap缩小位图时出现空指针异常
【发布时间】:2013-11-23 04:34:13
【问题描述】:

我有一个 imageView,它填充了用户从图库中选择的图像。然后,当单击名为“设置背景”的按钮时,此图像用于设置另一个活动的背景。当我选择图像时,它会显示在 imageView 中,但是当我按下“设置背景”按钮时,当我缩小位图时会得到 NPE。这是错误:

11-22 21:21:14.174: D/AndroidRuntime(24601): Shutting down VM
11-22 21:21:14.194: E/AndroidRuntime(24601): FATAL EXCEPTION: main
11-22 21:21:14.194: E/AndroidRuntime(24601): java.lang.NullPointerException
11-22 21:21:14.194: E/AndroidRuntime(24601):    at com.example.awesomefilebuilderwidget.Personalize.scaleDownBitmap(Personalize.java:119)
11-22 21:21:14.194: E/AndroidRuntime(24601):    at com.example.awesomefilebuilderwidget.Personalize.setBackgroundImageInDragAndDrop(Personalize.java:143)
11-22 21:21:14.194: E/AndroidRuntime(24601):    at com.example.awesomefilebuilderwidget.Personalize.onClick(Personalize.java:88)
11-22 21:21:14.194: E/AndroidRuntime(24601):    at android.view.View.performClick(View.java:2532)
11-22 21:21:14.194: E/AndroidRuntime(24601):    at android.view.View$PerformClick.run(View.java:9308)
11-22 21:21:14.194: E/AndroidRuntime(24601):    at android.os.Handler.handleCallback(Handler.java:587)
11-22 21:21:14.194: E/AndroidRuntime(24601):    at android.os.Handler.dispatchMessage(Handler.java:92)
11-22 21:21:14.194: E/AndroidRuntime(24601):    at android.os.Looper.loop(Looper.java:150)
11-22 21:21:14.194: E/AndroidRuntime(24601):    at android.app.ActivityThread.main(ActivityThread.java:4333)
 11-22 21:21:14.194: E/AndroidRuntime(24601):   at java.lang.reflect.Method.invokeNative(Native Method)
11-22 21:21:14.194: E/AndroidRuntime(24601):    at   com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
11-22 21:21:14.194: E/AndroidRuntime(24601):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
11-22 21:21:14.194: E/AndroidRuntime(24601):    at dalvik.system.NativeStart.main(Native Method)

这是我的 Personalize 课程:

public class Personalize extends Activity implements View.OnClickListener {
    Button button;
    ImageView image;
    ImageView image2;
    Button btnChangeImage;
    Button btnChangeImageForIcon;
    Button btnSetBackground;
    private static final int SELECT_PICTURE = 1;
    private static final int SELECT_PICTURE_2 = 2;
    private static final int RESULT_ICON = 20;
    private String selectedImagePath;
    Bitmap background;
    Bitmap b2;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.personalize);
        Log.d("Personalize", "OnCreate called");

        image = (ImageView) findViewById(R.id.imageView1);
        image2 = (ImageView) findViewById(R.id.imageView2Icon);

        Button btnChangeImage = (Button) findViewById(R.id.btnChangeImage);
        btnChangeImage.setOnClickListener(this);

        Button btnChangeImageForIcon = (Button) findViewById(R.id.btnChangeImageForIcon);
        btnChangeImageForIcon.setOnClickListener(this);

        Button btnSetBackground = (Button) findViewById(R.id.btnSetBackground);
        btnSetBackground.setOnClickListener(this);

        Button btnLinkToFeedback = (Button) findViewById(R.id.btnLinkToFeedback);

        Button btnSetIcon = (Button) findViewById(R.id.btnSetIcon);
        btnSetIcon.setOnClickListener(this);

        // Link to Feedback Screen
        btnLinkToFeedback.setOnClickListener(new View.OnClickListener() {

            public void onClick(View view) {
                Intent i = new Intent(getApplicationContext(), Feedback.class);
                startActivity(i);
                Log.d("Personalize", "LinkToFeedBack called");
                finish();
            }
        });

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.btnChangeImage:
            launchImageChooser();
            break;
        case R.id.btnChangeImageForIcon:
            launchImageChooser2();
            break;
        case R.id.btnSetBackground:
            setBackgroundImageInDragAndDrop();
            break;
        case R.id.btnSetIcon:
            setIconImageInWidget();
            break;
        }
    }

    private void setIconImageInWidget() {
        // TODO Auto-generated method stub
        Log.d("Personalize", "setIconImageInWidget() called");
        Intent i = getIntent();
        // Convert bitmap to byte array to send back to activity
        // See:
        // http://stackoverflow.com/questions/11010386/send-bitmap-using-intent-android
        scaleDownBitmapForIcon(b2, 500, this.getBaseContext());
        Log.d("Personalize", "Scale Bitmap Chosen For Icon");
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        b2.compress(Bitmap.CompressFormat.PNG, 100, stream);
        byte[] byteArray = stream.toByteArray();

        i.putExtra("myIconBitmap", byteArray);
        setResult(RESULT_ICON, i);
        finish();
    }

    public static Bitmap scaleDownBitmap(Bitmap background, int newHeight, Context c) {

        final float densityMultiplier = c.getResources().getDisplayMetrics().density;

        int h = (int) (500 * densityMultiplier);
        int w = (int) (h * background.getWidth() / ((double) background.getHeight()));

        background = Bitmap.createScaledBitmap(background, w, h, true);
        // TO SOLVE LOOK AT
        // HERE:http://stackoverflow.com/questions/15517176/passing-bitmap-to-other-activity-getting-message-on-logcat-failed-binder-transac
        return background;
    }

    public static Bitmap scaleDownBitmapForIcon(Bitmap b2, int newHeight, Context c) {

        final float densityMultiplier = c.getResources().getDisplayMetrics().density;

        int h = (int) (500 * densityMultiplier);
        int w = (int) (h * b2.getWidth() / ((double) b2.getHeight()));

        b2 = Bitmap.createScaledBitmap(b2, w, h, true);
        // TO SOLVE LOOK AT
        // HERE:http://stackoverflow.com/questions/15517176/passing-bitmap-to-other-activity-getting-message-on-logcat-failed-binder-transac
        return b2;
    }

    private void setBackgroundImageInDragAndDrop() {
        Log.d("Personalize", "setBackgroundImageInDragAndDrop() called");
        Intent i = getIntent();
        // Convert bitmap to byte array to send back to activity
        // See:
        // http://stackoverflow.com/questions/11010386/send-bitmap-using-intent-android
        scaleDownBitmap(background, 500, this.getBaseContext());
        Log.d("Personalize", "Scale Bitmap Chosen");
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        background.compress(Bitmap.CompressFormat.PNG, 100, stream);
        byte[] byteArray = stream.toByteArray();

        i.putExtra("myBackgroundBitmap", byteArray);
        setResult(RESULT_OK, i);
        finish();
    }

    private void launchImageChooser() {
        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        startActivityForResult(intent, SELECT_PICTURE);
        Log.d("Personalize", "launchImageChooser called");
    }

    private void launchImageChooser2() {
        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        startActivityForResult(intent, SELECT_PICTURE_2);
        Log.d("Personalize", "launchImageChooser2 called");
    }

    public String getPath(Uri uri) {
        String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        String imagePath = cursor.getString(column_index);
        if (cursor != null) {
            cursor.close();
        }
        return imagePath;
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (resultCode == RESULT_OK) {
            if (requestCode == SELECT_PICTURE) {
                Uri selectedImageUri = data.getData();
                selectedImagePath = getPath(selectedImageUri);
                background = getAndDecodeImage(selectedImagePath);
                if (background != null) {
                    image.setImageBitmap(background);
                }
            } else if (requestCode == SELECT_PICTURE_2) {
                Uri selectedImageUri = data.getData();
                selectedImagePath = getPath(selectedImageUri);
                b2 = getAndDecodeImage(selectedImagePath);
                if (b2 != null) {
                    image2.setImageBitmap(b2);
                }
            }
        }
    }

    @Override
    protected void onPause() {
        SharedPreferences sp = getSharedPreferences("AppSharedPref", 1); // open
                                                                            // shared
                                                                            // preferences
                                                                            // with
                                                                            // name
                                                                            // AppSharedPref
        Editor editor = sp.edit();
        editor.putString("ImagePath", selectedImagePath); // Store
                                                            // selectedImagePath
                                                            // with key
                                                            // "ImagePath". This
                                                            // key will be then
                                                            // used to retrieve
                                                            // data.
        editor.commit();
        super.onPause();
        Log.d("Personalize", "onPause() called and selectedImagePath saved");
    }

    @Override
    protected void onResume() {
        SharedPreferences sp = getSharedPreferences("AppSharedPref", 1);
        selectedImagePath = sp.getString("ImagePath", "");
        super.onResume();
        Log.d("Personalize", "onResume() called and images uploaded");
        Log.d("Personalize", "Now set the image as background");
        background = getAndDecodeImage(selectedImagePath);
        if (background != null) {
            image.setImageBitmap(background);
        }
        if (b2 != null) {
            image2.setImageBitmap(b2);
        }
    }

    private Bitmap getAndDecodeImage(String selectedImagePath) {
        try {
            Log.d("Personalize", "selectedImagePath: " + selectedImagePath);
            FileInputStream fileis = new FileInputStream(selectedImagePath);
            BufferedInputStream bufferedstream = new BufferedInputStream(fileis);
            byte[] bMapArray = new byte[bufferedstream.available()];
            bufferedstream.read(bMapArray);
            Bitmap bMap = BitmapFactory.decodeByteArray(bMapArray, 0, bMapArray.length);

            if (fileis != null) {
                fileis.close();
            }
            if (bufferedstream != null) {
                bufferedstream.close();
            }
            return bMap;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public boolean saveImageToInternalStorage(Bitmap image) {
        try {
            FileOutputStream fos = this.openFileOutput("desiredFilename.png", Context.MODE_PRIVATE);
            image.compress(Bitmap.CompressFormat.PNG, 100, fos);
            fos.close();
            return true;
        } catch (Exception e) {
            return false;
        }
    }

}

更具体地说,这里是行

119

int w= (int) (h * background.getWidth()/((double) background.getHeight()));

143

scaleDownBitmap(background, 500, this.getBaseContext());

显然background 正在返回 null 但我不知道为什么。

请帮忙!

添加:

这是通往 NPE 的 LogCat:

11-22 21:33:37.650: D/D&D(25036): LinkToPersonalize called
11-22 21:33:37.710: D/Personalize(25036): OnCreate called
11-22 21:33:37.720: D/Personalize(25036): onResume() called and images uploaded
11-22 21:33:37.720: D/Personalize(25036): Now set the image as background
11-22 21:33:37.720: D/Personalize(25036): selectedImagePath: 
11-22 21:33:37.720: D/skia(25036): --- SkImageDecoder::Factory returned null
11-22 21:33:38.300: D/Personalize(25036): launchImageChooser called
11-22 21:33:38.320: D/Personalize(25036): onPause() called and selectedImagePath saved
11-22 21:33:41.593: D/Personalize(25036): selectedImagePath: /mnt/sdcard/paintjoy/112411_143853.png
11-22 21:33:41.643: D/dalvikvm(25036): GC_CONCURRENT freed 80K, 44% free 3178K/5639K, external 3701K/4622K, paused 2ms+2ms
11-22 21:33:41.673: D/dalvikvm(25036): GC_EXTERNAL_ALLOC freed <1K, 44% free 3178K/5639K, external 3701K/4622K, paused 25ms
11-22 21:33:41.693: D/Personalize(25036): onResume() called and images uploaded
11-22 21:33:41.693: D/Personalize(25036): Now set the image as background
11-22 21:33:41.693: D/Personalize(25036): selectedImagePath: 
11-22 21:33:41.693: D/skia(25036): --- SkImageDecoder::Factory returned null
11-22 21:33:42.654: D/Personalize(25036): setBackgroundImageInDragAndDrop() called
11-22 21:33:42.654: D/AndroidRuntime(25036): Shutting down VM

更新: 接收类中的 onActivityResult:

         @Override 
     protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
     super.onActivityResult(requestCode, resultCode, data); 
     Log.i("Drag_and_Drop_App", "requestCode: " + requestCode + ", resultCode: " + resultCode); 

     if(requestCode == SET_BACKGROUND && resultCode == RESULT_OK){ 
     byte[] byteArray = data.getByteArrayExtra("myBackgroundBitmap"); 
     Bitmap myBackground = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length); 
     setBackgroundImage(myBackground); 
     } 
     else if(requestCode == RESULT_ICON){
         byte[] byteArray = data.getByteArrayExtra("myIconBitmap"); 
         Bitmap myIcon = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length); 
         setBackgroundImageForIcon(myIcon); 
         Log.d("Drag_and_Drop_App", "Icon is set");
     }
     } 

设置背景图片:

         @SuppressLint("NewApi") 
     private void setBackgroundImage(Bitmap bitmap) { 
     RelativeLayout yourBackgroundView = (RelativeLayout) findViewById(R.id.rl_drag_and_drop_app); 

     Drawable d = new BitmapDrawable(getResources(), bitmap); 

     if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { 
     yourBackgroundView.setBackgroundDrawable(d); 
     } else { 
     yourBackgroundView.setBackground(d); 
     Log.d("Drag_and_Drop_App", "Background is set");
     } 
     } 

setBackgroundImageForIcon:

         @SuppressLint("NewApi") 
     private void setBackgroundImageForIcon(Bitmap bitmap) { 
         Log.d("Drag_and_Drop_App", "Icon...");
     ImageView ivICON = (ImageView) findViewById(R.id.bwidgetOpen);

     BitmapDrawable dq = new BitmapDrawable(getResources(), bitmap); 

     if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { 
     // ivICON.setImageDrawable(dq);
         ivICON.setImageResource(R.drawable.pattern1);
     } else { 
    // ivICON.setImageDrawable(dq);
     ivICON.setImageResource(R.drawable.pattern1);
     Log.d("Drag_and_Drop_App", "Icon is set");
     } 
     }

整个类(没有不相关的东西):

package com.example.awesomefilebuilderwidget;

IMPORTS

public class Drag_and_Drop_App extends Activity {
private static final int SET_BACKGROUND = 10;
private static final int RESULT_ICON = 20;

private ListView mListAppInfo;
// Search EditText
EditText inputSearch;
public AppInfoAdapter adapter;
final SwipeDetector swipeDetector = new SwipeDetector();

//For GridView
private int draggedIndex = -1;
private BaseAdapter adapterGV;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // set layout for the main screen
    setContentView(R.layout.drag_and_drop_app);

public Bitmap getThumbnail(String filename) { 
     Bitmap thumbnail = null; 
     try { 
     File filePath = this.getFileStreamPath(filename); 
     FileInputStream fi = new FileInputStream(filePath); 
     thumbnail = BitmapFactory.decodeStream(fi); 
     } catch (Exception ex) { 
     Log.e("getThumbnail() on internal storage", ex.getMessage()); 
     } 
     return thumbnail; 
     } 

public String getPath(Uri uri) {
    String[] projection = { MediaStore.Images.Media.DATA };
    Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
    int column_index = cursor
            .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    cursor.moveToFirst();
    String imagePath = cursor.getString(column_index);
    if(cursor != null) {
    cursor.close();
    }
    return imagePath;
}

     @Override 
     protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
     super.onActivityResult(requestCode, resultCode, data); 
     Log.i("Drag_and_Drop_App", "requestCode: " + requestCode + ", resultCode: " + resultCode); 

     if(requestCode == SET_BACKGROUND && resultCode == RESULT_OK){ 
     byte[] byteArray = data.getByteArrayExtra("myBackgroundBitmap"); 
     Bitmap myBackground = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length); 
     setBackgroundImage(myBackground); 
     } 
     else if(requestCode == RESULT_ICON){
         byte[] byteArray = data.getByteArrayExtra("myIconBitmap"); 
         Bitmap myIcon = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length); 
         setBackgroundImageForIcon(myIcon); 
         Log.d("Drag_and_Drop_App", "Icon is set");
     }
     } 


     @SuppressLint("NewApi") 
     private void setBackgroundImage(Bitmap bitmap) { 
     RelativeLayout yourBackgroundView = (RelativeLayout) findViewById(R.id.rl_drag_and_drop_app); 

     Drawable d = new BitmapDrawable(getResources(), bitmap); 

     if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { 
     yourBackgroundView.setBackgroundDrawable(d); 
     } else { 
     yourBackgroundView.setBackground(d); 
     Log.d("Drag_and_Drop_App", "Background is set");
     } 
     } 

     @SuppressLint("NewApi") 
     private void setBackgroundImageForIcon(Bitmap bitmap) { 
         Log.d("Drag_and_Drop_App", "Icon...");
     ImageView ivICON = (ImageView) findViewById(R.id.bwidgetOpen);

     BitmapDrawable dq = new BitmapDrawable(getResources(), bitmap); 

     if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { 
     // ivICON.setImageDrawable(dq);
         ivICON.setImageResource(R.drawable.pattern1);
     } else { 
    // ivICON.setImageDrawable(dq);
     ivICON.setImageResource(R.drawable.pattern1);
     Log.d("Drag_and_Drop_App", "Icon is set");
     } 
     } 

     } 

【问题讨论】:

    标签: android bitmap nullpointerexception


    【解决方案1】:

    我认为问题在于您在 selectedImagePath 实际返回之前保存了它

    目前,您将selectedImagePath 保存到SharedPreferences 中的onPause 函数中, 但是onPause函数会在你调用onActivityResult之前被调用, 所以这意味着你将一个空值保存到 SharedPreferences 并在 onResume 中取回它,这将导致 NPE。

    只需将onPause中的保存部分移动到onActivtyResult的末尾即可。

    希望对您有所帮助。

    【讨论】:

    • 好的,谢谢,保存了 imageView 的图像路径...我还需要帮助保存 imagePaths 以在我设置背景时使用(我会将编码添加到“已更新") 你能帮我解决这个问题吗?
    • 这也修复了 NPE
    • 我不明白你的问题,你想保存图像路径并将其发送回接收类而不是发送整个位图?如果这是真的,因为您已经将 imagePaths 保存到 SharePreference,所以您可以像在 Personalize 类的 onResume 函数中一样将其取回。或者在setBackgroundImageInDragAndDropPersonalize 中,您可以将imagePaths 放在Intent 中,如i.putExtra("selectedImagePath", selectedImagePath);,然后通过Drag_and_Drop_App 将其取回Drag_and_Drop_ApponActivityResult
    • 好的,所以我想做的是,当我在 setBackgroundImage 中使用yourBackgroundView.setBackground(d); 设置背景时,我想让它保持该图像作为背景。我想我可以包括你上面所说的第二部分(使用Intent 中的imagePath)然后以某种方式使用它?希望这是有道理的。
    • 目前,当用户选择图像并将该图像放入 imageView(如预览)时,我保存了 imagePaths,然后当他们按下按钮时,imageView 中的图像被设置为背景
    【解决方案2】:

    试试这个

    更新这个方法

    private Bitmap getAndDecodeImage(String selectedImagePath) {
            try {
                // Decode image size
                BitmapFactory.Options o = new BitmapFactory.Options();
                o.inJustDecodeBounds = true;
                BitmapFactory.decodeFile(selectedImagePath, o);
                // The new size we want to scale to
                final int REQUIRED_SIZE = 500;
    
                // Find the correct scale value. It should be the power of 2.
                int scale = 1;
                while (o.outWidth / scale / 2 >= REQUIRED_SIZE && o.outHeight / scale / 2 >= REQUIRED_SIZE)
                    scale *= 2;
    
                // Decode with inSampleSize
                BitmapFactory.Options o2 = new BitmapFactory.Options();
                o2.inSampleSize = scale;
                return BitmapFactory.decodeFile(selectedImagePath, o2);
            } catch (Throwable e) {
                e.printStackTrace();
            }
            return null;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多