尝试访问图像内容信息时,Cursor返回null(旋转)

时间:2013-07-28 19:32:03

标签: android android-intent

简单的概念,但我失败了。我的应用程序要求提供图像,我想为用户提供使用图库,文件浏览器或相机来获取图像的选项。然后将图像旋转,缩放并上传到服务器。

首先我创建了意图。

protected void openImageIntent() {

// Determine Uri of camera image to save.
final File root = new File(Environment.getExternalStorageDirectory() + File.separator + "tpics" + File.separator);
root.mkdirs();
final String fname = "img_"+ System.currentTimeMillis() + ".jpg";
final File sdImageMainDirectory = new File(root, fname);
outputFileUri = Uri.fromFile(sdImageMainDirectory);

    // Camera.
    final List<Intent> cameraIntents = new ArrayList<Intent>();
    final Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    final PackageManager packageManager = getPackageManager();
    final List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0);
    for(ResolveInfo res : listCam) {
        final String packageName = res.activityInfo.packageName;
        final Intent intent = new Intent(captureIntent);
        intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
        intent.setPackage(packageName);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
        cameraIntents.add(intent);
    }

    // Filesystem.
    final Intent galleryIntent = new Intent();
    galleryIntent.setType("image/*");
    galleryIntent.setAction(Intent.ACTION_GET_CONTENT);

    // Chooser of filesystem options.
    final Intent chooserIntent = Intent.createChooser(galleryIntent, "Select Source");

    // Add the camera options.
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[]{}));

    startActivityForResult(chooserIntent, Constants.PICK_EXISTING_PHOTO_RESULT_CODE);
}

然后,在选择图像后,我有了onActivityResult代码。

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
    case Constants.PICK_EXISTING_PHOTO_RESULT_CODE: {
        if (resultCode == Activity.RESULT_OK) {

            Uri selectedImageUri = (data == null ? true : MediaStore.ACTION_IMAGE_CAPTURE.equals(data.getAction())) ? outputFileUri : (data == null ? null : data.getData());
            Log.d("URI", selectedImageUri.toString());
            trophyImage = new TrophyImage(mCtx, selectedImageUri);
            try {
                imageBytes = trophyImage.scaleImage();
                image.setImageBitmap(BitmapFactory.decodeByteArray(
                        imageBytes, 0, imageBytes.length));
                image.invalidate();
            } catch (IOException e) {
                Utility.handleExternalError(
                        mCtx,
                        getString(R.string.error_error),
                        getString(R.string.error_unable_to_scale_image_is_is_corrupt));
            }
        } else {
            Utility.showToast(mCtx, "No image selected.");
        }
        break;
    }

这是我的TrophyImage类。

public class TrophyImage {

private Context mCtx;
private Uri mImageUri;
private static int MAX_IMAGE_DIMENSION = 720;
private String type;
private JSONServerClient mClient;

public TrophyImage(Context mCtx, Uri imageUri) {
    this.mCtx = mCtx;
    this.mImageUri = imageUri;
    this.mClient = new JSONServerClient((Activity) mCtx);
}

/**
 * Scales and orients images taken from the gallery.
 * 
 * @param context
 * @param photoUri
 * @return
 * @throws IOException
 */
public byte[] scaleImage() throws IOException {
    InputStream is = mCtx.getContentResolver().openInputStream(mImageUri);
    BitmapFactory.Options dbo = new BitmapFactory.Options();
    dbo.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(is, null, dbo);
    is.close();

    int rotatedWidth, rotatedHeight;
    int orientation = getOrientation();

    if (orientation == 90 || orientation == 270) {
        rotatedWidth = dbo.outHeight;
        rotatedHeight = dbo.outWidth;
    } else {
        rotatedWidth = dbo.outWidth;
        rotatedHeight = dbo.outHeight;
    }

    Bitmap srcBitmap;
    is = mCtx.getContentResolver().openInputStream(mImageUri);
    if (rotatedWidth > MAX_IMAGE_DIMENSION
            || rotatedHeight > MAX_IMAGE_DIMENSION) {
        float widthRatio = ((float) rotatedWidth)
                / ((float) MAX_IMAGE_DIMENSION);
        float heightRatio = ((float) rotatedHeight)
                / ((float) MAX_IMAGE_DIMENSION);
        float maxRatio = Math.max(widthRatio, heightRatio);

        // Create the bitmap from file
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = (int) maxRatio;
        srcBitmap = BitmapFactory.decodeStream(is, null, options);
    } else {
        srcBitmap = BitmapFactory.decodeStream(is);
    }
    is.close();

    /*
     * if the orientation is not 0 (or -1, which means we don't know), we
     * have to do a rotation.
     */
    if (orientation > 0) {
        Matrix matrix = new Matrix();
        matrix.postRotate(orientation);

        srcBitmap = Bitmap.createBitmap(srcBitmap, 0, 0,
                srcBitmap.getWidth(), srcBitmap.getHeight(), matrix, true);
    }

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    if (type.equals("image/png")) {
        srcBitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
    } else if (type.equals("image/jpg") || type.equals("image/jpeg")) {
        srcBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
    }
    byte[] bMapArray = baos.toByteArray();
    baos.close();
    return bMapArray;
}

public int getOrientation() {

    /* it's on the external media. */
    Log.d("mImageUri", mImageUri.toString());
    Cursor cursor = mCtx.getContentResolver().query(mImageUri,
            new String[] { MediaStore.Images.ImageColumns.ORIENTATION },
            null, null, null);

    if (cursor.getCount() != 1) {
        return -1;
    }

    cursor.moveToFirst();
    return cursor.getInt(0);
}

public String uploadPhoto(final byte[] imageBytes, final String fileName) throws IOException {
    String fileID = null;
    String encodedImage = Base64.encodeToString(imageBytes, Base64.DEFAULT);
    try {
        JSONObject dataOut = new JSONObject();
        dataOut.put("file", encodedImage);
        dataOut.put("filename", fileName);
        mClient.call(dataOut, JSONServerClient.FILE_UPLOAD);
        // get the result so we know the file id (fid)
        // and we can assign it to the correct field.
        String js = mClient.getResponse();
        JSONObject jo = new JSONObject(js);
        fileID = jo.getString("fid");
    } catch (JSONException e) {
        e.printStackTrace();
    } 
    return fileID;
};

public String getFileName() {
    return Utility.getFileNameByUri(mImageUri, mCtx);
}

public Uri getmImageUri() {
    return mImageUri;
}

}

我在TrophyImage.getOrientation()的第一行得到一个nullPointerException(第118行)

if (cursor.getCount() != 1)

我测试了游标的值,当然,它是null。我无法弄清楚为什么它是空的。它似乎应该返回我需要的数据。

以防万一需要它。这是整个错误堆栈。

07-28 14:15:51.573: E/AndroidRuntime(29734): FATAL EXCEPTION: main
07-28 14:15:51.573: E/AndroidRuntime(29734): java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=2, result=-1, data=Intent { dat=file:///storage/sdcard0/tpics/img_1375038937506.jpg }} to activity {com.seine.trophy.main/com.seine.trophy.main.TrophyCreate}: java.lang.NullPointerException
07-28 14:15:51.573: E/AndroidRuntime(29734):    at android.app.ActivityThread.deliverResults(ActivityThread.java:3322)
07-28 14:15:51.573: E/AndroidRuntime(29734):    at android.app.ActivityThread.handleSendResult(ActivityThread.java:3365)
07-28 14:15:51.573: E/AndroidRuntime(29734):    at android.app.ActivityThread.access$1200(ActivityThread.java:141)
07-28 14:15:51.573: E/AndroidRuntime(29734):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1315)
07-28 14:15:51.573: E/AndroidRuntime(29734):    at android.os.Handler.dispatchMessage(Handler.java:99)
07-28 14:15:51.573: E/AndroidRuntime(29734):    at android.os.Looper.loop(Looper.java:137)
07-28 14:15:51.573: E/AndroidRuntime(29734):    at android.app.ActivityThread.main(ActivityThread.java:5059)
07-28 14:15:51.573: E/AndroidRuntime(29734):    at java.lang.reflect.Method.invokeNative(Native Method)
07-28 14:15:51.573: E/AndroidRuntime(29734):    at java.lang.reflect.Method.invoke(Method.java:511)
07-28 14:15:51.573: E/AndroidRuntime(29734):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792)
07-28 14:15:51.573: E/AndroidRuntime(29734):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555)
07-28 14:15:51.573: E/AndroidRuntime(29734):    at dalvik.system.NativeStart.main(Native Method)
07-28 14:15:51.573: E/AndroidRuntime(29734): Caused by: java.lang.NullPointerException
07-28 14:15:51.573: E/AndroidRuntime(29734):    at com.seine.trophy.main.TrophyImage.getOrientation(TrophyImage.java:118)
07-28 14:15:51.573: E/AndroidRuntime(29734):    at com.seine.trophy.main.TrophyImage.scaleImage(TrophyImage.java:58)
07-28 14:15:51.573: E/AndroidRuntime(29734):    at com.seine.trophy.main.TrophyCreate.onActivityResult(TrophyCreate.java:333)
07-28 14:15:51.573: E/AndroidRuntime(29734):    at android.app.Activity.dispatchActivityResult(Activity.java:5242)
07-28 14:15:51.573: E/AndroidRuntime(29734):    at android.app.ActivityThread.deliverResults(ActivityThread.java:3318)
07-28 14:15:51.573: E/AndroidRuntime(29734):    ... 11 more

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

是的,他们的关键是返回的uri不是格式内容:// ..这告诉我图像没有被添加到媒体库,所以当然光标是空的。解决方案是改变这样的Intent创建。

protected void openImageIntent() {

    final String fname = "img_" + System.currentTimeMillis() + ".jpg";
    ContentValues values = new ContentValues();
    values.put(MediaStore.Images.Media.TITLE, fname);
    values.put(MediaStore.Images.Media.DESCRIPTION,
            "Image capture by camera");
    // outputFileUri is the current activity attribute, define and save it
    // for later usage (also in onSaveInstanceState)
    outputFileUri = getContentResolver().insert(
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

    // Camera.
    final List<Intent> cameraIntents = new ArrayList<Intent>();
    final Intent captureIntent = new Intent(
            android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    final PackageManager packageManager = getPackageManager();
    final List<ResolveInfo> listCam = packageManager.queryIntentActivities(
            captureIntent, 0);
    for (ResolveInfo res : listCam) {
        final String packageName = res.activityInfo.packageName;
        final Intent intent = new Intent(captureIntent);
        intent.setComponent(new ComponentName(res.activityInfo.packageName,
                res.activityInfo.name));
        intent.setPackage(packageName);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
        cameraIntents.add(intent);
    }

    // Filesystem.
    final Intent galleryIntent = new Intent();
    galleryIntent.setType("image/*");
    galleryIntent.setAction(Intent.ACTION_GET_CONTENT);

    // Chooser of filesystem options.
    final Intent chooserIntent = Intent.createChooser(galleryIntent,
            "Select Source");

    // Add the camera options.
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS,
            cameraIntents.toArray(new Parcelable[] {}));

    startActivityForResult(chooserIntent,
            Constants.PICK_EXISTING_PHOTO_RESULT_CODE);
}

现在,图像捕获是mediastore的一部分,传递url时游标值不为null。