Android:来自相机和图库运行时异常的图片

Posted

技术标签:

【中文标题】Android:来自相机和图库运行时异常的图片【英文标题】:Android:picture from Camera and gallery runtime exception 【发布时间】:2013-02-23 17:57:35 【问题描述】:

以下是我的错误日志:

 03-08 13:20:36.193: E/androidRuntime(9486): FATAL EXCEPTION: main
   03-08 13:20:36.193: E/AndroidRuntime(9486): java.lang.RuntimeException: Unable to    resume activity com.example.camtest1/com.example.camtest1.MainActivity: android.database.StaleDataException: Attempted to access a cursor after it has been closed.
  03-08 13:20:36.193: E/AndroidRuntime(9486):   at  android.app.ActivityThread.performResumeActivity(ActivityThread.java:2639)
  03-08 13:20:36.193: E/AndroidRuntime(9486):   at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2667)
  03-08 13:20:36.193: E/AndroidRuntime(9486):   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1279)
  03-08 13:20:36.193: E/AndroidRuntime(9486):   at android.os.Handler.dispatchMessage(Handler.java:99)
  03-08 13:20:36.193: E/AndroidRuntime(9486):   at android.os.Looper.loop(Looper.java:137)
  03-08 13:20:36.193: E/AndroidRuntime(9486):   at android.app.ActivityThread.main(ActivityThread.java:4935)
  03-08 13:20:36.193: E/AndroidRuntime(9486):   at java.lang.reflect.Method.invokeNative(Native Method)
  03-08 13:20:36.193: E/AndroidRuntime(9486):   at java.lang.reflect.Method.invoke(Method.java:511)
  03-08 13:20:36.193: E/AndroidRuntime(9486):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
  03-08 13:20:36.193: E/AndroidRuntime(9486):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
  03-08 13:20:36.193: E/AndroidRuntime(9486):   at dalvik.system.NativeStart.main(Native Method)
  03-08 13:20:36.193: E/AndroidRuntime(9486): Caused by: android.database.StaleDataException: Attempted to access a cursor after it has been closed.
  03-08 13:20:36.193: E/AndroidRuntime(9486):   at android.database.BulkCursorToCursorAdaptor.throwIfCursorIsClosed(BulkCursorToCursorAdaptor.java:64)
  03-08 13:20:36.193: E/AndroidRuntime(9486):   at android.database.BulkCursorToCursorAdaptor.requery(BulkCursorToCursorAdaptor.java:133)
  03-08 13:20:36.193: E/AndroidRuntime(9486):   at android.database.CursorWrapper.requery(CursorWrapper.java:186)
  03-08 13:20:36.193: E/AndroidRuntime(9486):   at android.app.Activity.performRestart(Activity.java:5246)
  03-08 13:20:36.193: E/AndroidRuntime(9486):   at android.app.Activity.performResume(Activity.java:5272)
  03-08 13:20:36.193: E/AndroidRuntime(9486):   at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2629)
  03-08 13:20:36.193: E/AndroidRuntime(9486):   ... 10 more

我无法确定我的代码哪里出错了。以下是我尝试在三星处理完成后从图库中捕获或选择图片的代码:

   import java.io.ByteArrayOutputStream;
   import android.app.Activity;
   import android.app.AlertDialog;
   import android.content.DialogInterface;
   import android.content.Intent;
   import android.database.Cursor;
   import android.graphics.Bitmap;
   import android.graphics.BitmapFactory;
   import android.net.Uri;
   import android.os.Bundle;
   import android.provider.MediaStore;
   import android.view.View;
   import android.widget.Button;
   import android.widget.ImageView;
   import android.widget.Toast;

 public class MainActivity extends Activity 


String picturePath;
private static int RESULT_LOAD_IMAGE = 1;
private static final int PICK_FROM_GALLERY = 2;
int CAMERA_PIC_REQUEST = 1337; 
Bitmap thumbnail = null; 
private static final int OG=4; 

private static final int CAMERA_IMAGE_CAPTURE = 0;
Uri u;
ImageView imgview;
//int z=0;
String z=null;
byte b[];
String largeImagePath = "";
Uri uriLargeImage;
Uri uriThumbnailImage;
Cursor myCursor;





 public void imageCam(Bitmap thumbnail)
        Bitmap photo = thumbnail; 
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        photo.compress(Bitmap.CompressFormat.JPEG, 70, bos);
        b = bos.toByteArray();
        ImageView imageview = (ImageView)findViewById(R.id.imageView1);
    //  Bitmap bt=Bitmap.createScaledBitmap(photo, 200, 400, false);  
        imageview.setImageBitmap(photo);

    

  @Override
  public void onCreate(Bundle savedInstanceState) 
     super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Button bt = (Button)findViewById(R.id.button1);
    bt.setOnClickListener(onBTN);
    if( savedInstanceState != null ) 
        //if()
        Bitmap Zatang; 
        String B1 = savedInstanceState .getString("message");
        Toast.makeText(this, "SavedYeah"+B1, Toast.LENGTH_LONG).show();
        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inSampleSize = OG;
        // thumbnail = (BitmapFactory.decodeFile(picturePath));
        Zatang = BitmapFactory.decodeFile((B1), opts);
        System.gc();
        if(Zatang != null)
             Toast.makeText(this, "Success Zatang"+B1, Toast.LENGTH_LONG).show();
             imageCam(Zatang);

         
        String B12 = savedInstanceState .getString("Gallerymessage"); 
        if(B12 != null)
            Toast.makeText(this, "Recreated on Gallery", Toast.LENGTH_LONG).show();
            BitmapFactory.Options opts1 = new BitmapFactory.Options();
            opts.inSampleSize = OG;
           // thumbnail = (BitmapFactory.decodeFile(picturePath));
            thumbnail = BitmapFactory.decodeFile((B12), opts1);
            System.gc();
            imageCam(thumbnail);

        






private View.OnClickListener onBTN = new View.OnClickListener()
    public void onClick(View v)
        openNewGameDialog();
    
;
String []B = "Camera", "Gallery";


private void openNewGameDialog()
            new AlertDialog.Builder(this).setItems(B,new       DialogInterface.OnClickListener()
            public void onClick(DialogInterface dialoginterface,int i)
                if(i==0)
                    String BX1 =  android.os.Build.MANUFACTURER;

                    if(BX1.equalsIgnoreCase("samsung"))
                    Toast.makeText(getApplicationContext(), "Device man"+BX1, Toast.LENGTH_LONG).show();
                    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    startActivityForResult(intent, CAMERA_IMAGE_CAPTURE);

                    
                    else 
                         Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 
                         startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST); 
                    
                

                else if (i==1)
                     // Intent in = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                     // startActivityForResult(in, RESULT_LOAD_IMAGE);


                      Intent intent = new Intent(Intent.ACTION_PICK);
                      intent.setType("image/*");
                      startActivityForResult(intent, RESULT_LOAD_IMAGE);
                




           
           )
           .show();
   

protected void onActivityResult(int requestCode, int resultCode, Intent data)   
        super.onActivityResult(requestCode, resultCode, data);
         if(requestCode==CAMERA_IMAGE_CAPTURE && resultCode==Activity.RESULT_OK)

        // Describe the columns you'd like to have returned. Selecting from the Thumbnails location gives you both the Thumbnail Image ID, as well as the original image ID
         String[] projection = 
         MediaStore.Images.Thumbnails._ID,  // The columns we want
         MediaStore.Images.Thumbnails.IMAGE_ID,
         MediaStore.Images.Thumbnails.KIND,
         MediaStore.Images.Thumbnails.DATA;
         String selection = MediaStore.Images.Thumbnails.KIND + "="  + // Select only mini's
         MediaStore.Images.Thumbnails.MINI_KIND;

         String sort = MediaStore.Images.Thumbnails._ID + " DESC";

        //At the moment, this is a bit of a hack, as I'm returning ALL images, and just taking the latest one. There is a better way to narrow this down I think with a WHERE clause which is currently the selection variable
        myCursor = this.managedQuery(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, projection, selection, null, sort);

        long imageId = 0l;
        long thumbnailImageId = 0l;
        String thumbnailPath = "";

        try

            myCursor.moveToFirst();
            imageId = myCursor.getLong(myCursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails.IMAGE_ID));
            thumbnailImageId = myCursor.getLong(myCursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails._ID));
            thumbnailPath = myCursor.getString(myCursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails.DATA));
            
        finally
            myCursor.close();
            

            //Create new Cursor to obtain the file Path for the large image

                String[] largeFileProjection = 
                MediaStore.Images.ImageColumns._ID,
                MediaStore.Images.ImageColumns.DATA
                ;

                String largeFileSort = MediaStore.Images.ImageColumns._ID + " DESC";
                myCursor = this.managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, largeFileProjection, null, null, largeFileSort);
                largeImagePath = "";

                try
                    myCursor.moveToFirst();

                    //This will actually give yo uthe file path location of the image.
                    largeImagePath = myCursor.getString(myCursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATA));
                
                finallymyCursor.close();
                // These are the two URI's you'll be interested in. They give you a handle to the actual images
                uriLargeImage = Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, String.valueOf(imageId));
                uriThumbnailImage = Uri.withAppendedPath(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, String.valueOf(thumbnailImageId));

                // I've left out the remaining code, as all I do is assign the URI's to my own objects anyways...
                // Toast.makeText(this, ""+largeImagePath, Toast.LENGTH_LONG).show();
                // Toast.makeText(this, ""+uriLargeImage, Toast.LENGTH_LONG).show();
                // Toast.makeText(this, ""+uriThumbnailImage, Toast.LENGTH_LONG).show();


                if(largeImagePath != null )
                    Toast.makeText(this, "LARGE YES"+largeImagePath, Toast.LENGTH_LONG).show();

                     BitmapFactory.Options opts = new BitmapFactory.Options();
                     opts.inSampleSize = OG;
                     // thumbnail = (BitmapFactory.decodeFile(picturePath));
                     thumbnail = BitmapFactory.decodeFile((largeImagePath), opts);
                     System.gc();
                     if(thumbnail != null)
                         Toast.makeText(this, "Try Without Saved Instance", Toast.LENGTH_LONG).show();
                         imageCam(thumbnail);
                     




                if(uriLargeImage != null)


                    Toast.makeText(this, ""+uriLargeImage, Toast.LENGTH_LONG).show();





                if(uriThumbnailImage != null)


                    Toast.makeText(this, ""+uriThumbnailImage, Toast.LENGTH_LONG).show();



                



         
         if( requestCode == 1337 && resultCode== RESULT_OK)
                Bundle extras = data.getExtras();
                //  if (extras!=null)  
                if (extras.keySet().contains("data") )

                        BitmapFactory.Options options = new BitmapFactory.Options();
                        // options.inSampleSize = 1;
                        // options.inPurgeable = true;
                        // options.inInputShareable = true;
                        thumbnail = (Bitmap) extras.get("data");
                        //  image(thumbnail);
                        if (thumbnail != null)
                        Toast.makeText(this, "YES Thumbnail", Toast.LENGTH_LONG).show();
                            BitmapFactory.Options opt = new BitmapFactory.Options();
                            // options.inSampleSize = 1;
                            // options.inPurgeable = true;
                            // options.inInputShareable = true;
                            thumbnail = (Bitmap) extras.get("data");
                            imageCam(thumbnail);
                        

                    else

                    Uri imageURI = getIntent().getData();
                    ImageView imageview = (ImageView)findViewById(R.id.imageView1);
                    imageview.setImageURI(imageURI);

                    if(imageURI != null)
                    Toast.makeText(this, "YES Image Uri", Toast.LENGTH_LONG).show();

                    





                       // Toast.makeText(CreateProfile.this, "Picture NOt taken", Toast.LENGTH_LONG).show();
                    
                super.onActivityResult(requestCode, resultCode, data);  
         
         if (requestCode == RESULT_LOAD_IMAGE && resultCode == RESULT_OK && null != data)
                Uri selectedImage = data.getData();

                    String[] filePathColumn =  MediaStore.Images.Media.DATA ;
                    Cursor cursor = getContentResolver().query(selectedImage,filePathColumn, null, null, null);
                    cursor.moveToFirst();
                    int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
                    String picturePath = cursor.getString(columnIndex);
                    cursor.close();
                    BitmapFactory.Options opts = new BitmapFactory.Options();
                    opts.inSampleSize = OG;
                   // thumbnail = (BitmapFactory.decodeFile(picturePath));
                    thumbnail = BitmapFactory.decodeFile((picturePath), opts);
                    System.gc();
                    imageCam(thumbnail);

             

                 else
                 
                    // imgview.setBackgroundResource(R.drawable.bbtb);
                 

         
    @Override
    public void onSaveInstanceState(Bundle outState) 
       super.onSaveInstanceState(outState);
       outState.putString("message",largeImagePath );
       outState.putString("Gallerymessage",picturePath );


    

【问题讨论】:

我也遇到了同样的问题...你有解决办法吗??? 【参考方案1】:

我遇到了同样的问题,在某些设备/API 级别上,当使用相机意图时,会调用 onDestroy()。在我的 onDestroy 中,我像往常一样关闭了游标和数据库。

您可以通过检查数据库是否为 .open 和 cursor==null 来解决此问题: onActivityResult 或 onResume 然后在需要时重新打开并更新游标。

if (!database.isOpen() || database==null) 
    patternsdb helper = new patternsdb(main.this);
    database = helper.getWritableDatabase();

【讨论】:

以上是关于Android:来自相机和图库运行时异常的图片的主要内容,如果未能解决你的问题,请参考以下文章

Android 相机和图库

图片来自 Android 6 中的图库(棉花糖)

Android12.4 利用Intent读取图库中的图片

Android调用照相机和百度地图开发,百度地图显示界面覆盖了相机界面,求大神解答?

将相机图像上传到 Firebase

来自画廊工作的文件选择器,但它不适用于 android webview 中的相机