【问题标题】:Get path to image chosen from gallery(on SD card)获取从图库中选择的图像的路径(在 SD 卡上)
【发布时间】:2017-04-07 03:47:13
【问题描述】:

我根本无法获取从 SD 卡上的图库中选择的图像的路径,但存储在设备上的图像没有问题。有几十个类似或重复的问题,但没有一个有效。

最推荐的方法(@Commonsware)是使用ContentResolver 并调用openInputStream(),所以我尝试从openInputStream() 读取字节,然后创建一个临时文件并使用该路径,但运气不好。我的“读取字节数:”System.err.println 调用显示读取了 0 个字节。

我还尝试了thisthisthisthisthisthis,都没有工作。很多这些答案导致调用BitmapFactory#decodeStream(),问题是,我不在乎显示图像,我只需要路径!!。

请帮忙!

到目前为止的代码:

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

    if(resultCode == Activity.RESULT_OK){

        switch(requestCode){

            case SELECT_FROM_GALLERY:
                fromGallery = true;
                path = getRealPathFromURI(data.getData());
                System.err.println("*******path: " + path + "*********");

                break;

        }

    }

}

public String getRealPathFromURI(Uri contentUri) {
    String thePath = null;
    String[] filePathColumn = {MediaStore.Images.Media.DATA};
    Cursor cursor = getContext().getContentResolver().query(contentUri, filePathColumn, null, null, null);
    if(cursor.moveToFirst()){
        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        thePath = cursor.getString(columnIndex);
    }
    cursor.close();

    if(thePath == null){
        return getImagePathExternal(contentUri);
    }else {
        return thePath;
    }
}

public String getImagePathExternal(Uri uri){
    Cursor cursor = getContext().getContentResolver().query(uri, null, null, null, null);
    cursor.moveToFirst();
    String document_id = cursor.getString(0);
    document_id = document_id.substring(document_id.lastIndexOf(":")+1);
    cursor.close();

    cursor = getContext().getContentResolver().query(
            android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            null, MediaStore.Images.Media._ID + " = ? ", new String[]{document_id}, null);
    cursor.moveToFirst();
    String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
    cursor.close();

    if(path == null){

        System.err.println("****************trying bytes route******************");
        try{

            InputStream in = getContext().getContentResolver().openInputStream(uri);

            byte[] resultBuff = new byte[0];
            byte[] buff = new byte[1024];
            int k ;
            while((k = in.read(buff, 0, buff.length)) > -1) {
                byte[] tbuff = new byte[resultBuff.length + k]; // temp buffer size = bytes already read + bytes last read
                System.arraycopy(resultBuff, 0, tbuff, 0, resultBuff.length); // copy previous bytes
                System.arraycopy(buff, 0, tbuff, resultBuff.length, k);  // copy current lot
                resultBuff = tbuff; // call the temp buffer as your result buff
            }

            System.err.println("****************bytes read: "+resultBuff.length+" ******************");

            File tem = new File(_tempImageDir, "temp.jpg");

            FileOutputStream out = new FileOutputStream(tem);

            out.write(resultBuff, 0, resultBuff.length);

            return tem.getAbsolutePath();

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

    }

    return path;
}

Logcat(无论我使用哪种方法,此异常都不会改变):

E/AndroidRuntime: FATAL EXCEPTION: main
                                                                  Process: com.venon.nakomangsp, PID: 20610
                                                                  java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=132074, result=-1, data=Intent { dat=content://media/external/images/media/4147 (has extras) }} to activity {com.venon.nakomangsp/com.venon.nakomangsp.SignUpActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on a null object reference
                                                                      at android.app.ActivityThread.deliverResults(ActivityThread.java:4058)
                                                                      at android.app.ActivityThread.handleSendResult(ActivityThread.java:4101)
                                                                      at android.app.ActivityThread.access$1400(ActivityThread.java:177)
                                                                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1497)
                                                                      at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                      at android.os.Looper.loop(Looper.java:145)
                                                                      at android.app.ActivityThread.main(ActivityThread.java:5942)
                                                                      at java.lang.reflect.Method.invoke(Native Method)
                                                                      at java.lang.reflect.Method.invoke(Method.java:372)
                                                                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
                                                                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
                                                                   Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on a null object reference
                                                                      at id.zelory.compressor.ImageUtil.getScaledBitmap(ImageUtil.java:62)
                                                                      at id.zelory.compressor.ImageUtil.compressImage(ImageUtil.java:161)
                                                                      at id.zelory.compressor.Compressor.compressToFile(Compressor.java:48)
                                                                      at com.venon.nakomangsp.SignUpFragment.preparePicture(SignUpFragment.java:870)
                                                                      at com.venon.nakomangsp.SignUpFragment.onActivityResult(SignUpFragment.java:783)
                                                                      at android.support.v4.app.FragmentActivity.onActivityResult(FragmentActivity.java:165)
                                                                      at com.venon.nakomangsp.SignUpActivity.onActivityResult(SignUpActivity.java:37)
                                                                      at android.app.Activity.dispatchActivityResult(Activity.java:6549)
                                                                      at android.app.ActivityThread.deliverResults(ActivityThread.java:4054)
                                                                      at android.app.ActivityThread.handleSendResult(ActivityThread.java:4101) 
                                                                      at android.app.ActivityThread.access$1400(ActivityThread.java:177) 
                                                                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1497) 
                                                                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                      at android.os.Looper.loop(Looper.java:145) 
                                                                      at android.app.ActivityThread.main(ActivityThread.java:5942) 
                                                                      at java.lang.reflect.Method.invoke(Native Method) 
                                                                      at java.lang.reflect.Method.invoke(Method.java:372) 
                                                                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399) 
                                                                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194) 

【问题讨论】:

  • 没有路径。为什么要路径?
  • 图库中没有图片的路径?那不可能是因为如果我选择不在 SD 卡上的图像,我会得到一条路径。我需要它来制作图像的压缩版本并将其发送到我的服务器
  • 您不需要在BitmapFactory.decodeStream() 创建的位图上调用compress() 的路径。是什么让您认为您需要一条途径来做到这一点?
  • 表示您要从图库[SD卡]中选择的图像路径...???
  • @ianhanniballake 我没有使用它进行压缩,我使用的是需要压缩路径的自定义库。

标签: java android android-contentprovider android-sdcard android-gallery


【解决方案1】:

应用无法直接访问 SD 卡中的任何内容。因此,即使您可以获得某种“路径”,您的应用也无法从该位置读取任何内容。

可靠地访问这些文件内容的唯一方法是通过ContentResolver.openInputStream()(或其他open 方法,如果您需要AssetFileDescriptor 等)。

您绝对可以将文件复制到您的own cache directory,然后对图像做任何您想做的事情。

【讨论】:

  • 可以在不获取路径的情况下复制该文件吗?
  • @WaqasAhmedAnsari - 当然,你 openInputStream() 并将其写入 FileOutputStream。不需要路径。
  • 我明白了。刚刚发生了一些奇怪的行为。我从设备中删除了所有照片,只留下了 SD 卡上的照片,然后从我的应用程序外部拍摄了一张照片并将其保存到设备中,中提琴......一切都按预期工作。我从两者中选择了一张照片位置并设法在不使用 openInputStream 的情况下获取路径。你知道为什么会发生这种情况吗?
  • 我将代码包装在一个 try-catch 块中,并将 openInputStream 路由作为后备,因为我怀疑它是否适用于其他 android 版本
  • 由于openInputStream 确实适用于任何content:// Uri(如SD 卡中的那些)或file:// Uri,我只使用它并跳过黑客。
【解决方案2】:

如果你使用API​​ 24,那么你应该使用FileProvide,官方网站的介绍:https://developer.android.com/reference/android/support/v4/content/FileProvider.html 你应该这样写:

  1. 使用元素的子元素,在 XML 中指定存储区域的内容和路径。例如,以下 pathsmann 告诉 FileProvider 您打算为您的私有文件区域的图像/子目录请求内容 URI。

    <Manifest>
        <Application>
            <Provider
                Android: name = "android.support.v4.content.FileProvider"
                Android: authorities = "com.mydomain.fileprovider"
                Android: exported = "false"
                Android: grantUriPermissions = "true"
               <Meta-data
               Android: name = "android.support.FILE_PROVIDER_PATHS"
               Android: resource = "@ xml / file_paths" />
            </ Provider>
        </ Application>
    </ Manifest>
    
    
    <? Xml version = "1.0" encoding = "utf-8"?>
    <Resources>
        <Paths>
            <External-path
                Name = "external_files"
                Path = "." />
            <Root-path
                Name = "external_files"
                Path = "/ storage /" />
        </ Paths> `enter code here`
    </ Resources>
    
  2. 第三步:文件就是你的路径

    Uri contentUri = getUriForFile (getContext (), getPackageName () + ".provider", file);
    

【讨论】:

    【解决方案3】:

    不同的手机有一些不同的行为。经过大量研究和尝试不同的可能性后,我想出了一个适用于我测试过的所有手机的解决方案(LG G2、Nexus 5、ZTE、Note 5、Nexus 6、Infinix Note 3 Pro 和其他一些我不记得了)。如果它有效,试试这个。根据你的需要服用。它还包括从相机捕获图片,复制它并获取它的路径。

    //SELECT PICTURE FROM GALLERY OR CAPTURE FROM CAMERA
    private void selectPicture(View view) {
        tempView = view;
        final CharSequence[] items;
        if(view.getClass().getName().equalsIgnoreCase("android.widget.ImageView"))
                items = new CharSequence[]{ "Take Photo", "Choose from Library", "Remove Photo", "Cancel" };
        else items = new CharSequence[]{ "Take Photo", "Choose from Library", "Cancel" };
    
        AlertDialog.Builder builder = new AlertDialog.Builder(ActivityAddMemory.this);
        builder.setTitle("Add Image");
        builder.setItems(items, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int item) {
                if (items[item].equals("Take Photo")) {
                    showCamera();
                } else if (items[item].equals("Choose from Library")) {
                    Intent intent = new Intent(
                            Intent.ACTION_PICK,
                            MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                    intent.setType("image/*");
                    startActivityForResult(
                            Intent.createChooser(intent, "Select File"),
                            SELECT_FILE);
                } else if(items[item].equals("Remove Photo")) {
                    imgLinearLayout.removeView(tempView);
                    imagesList.remove(tempView.getId());
                    if(imagesList.size() < 1) {
                        imgLinearLayout.setVisibility(View.GONE);
                    }
    
                    if(btnAddPhoto.getVisibility() == View.GONE)
                        btnAddPhoto.setVisibility(View.VISIBLE);
                } else if (items[item].equals("Cancel")) {
                    dialog.dismiss();
                }
            }
        });
        builder.show();
    }
    
    
    //OPEN CAMERA IF WANT TO CAPTURE
    private void showCamera() {
    
        try {
            File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "DCIM");
            if (!file.exists()) {
                file.mkdirs();
            }
    
            File localFile2 = new File(file + File.separator + "IMG_" + String.valueOf(System.currentTimeMillis()) + ".jpg");
            imageUri = Uri.fromFile(localFile2);
    
            Intent cameraIntent = new Intent("android.media.action.IMAGE_CAPTURE");
    
            cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                cameraIntent.setClipData(ClipData.newRawUri(null, Uri.fromFile(localFile2)));
            }
    
            startActivityForResult(cameraIntent, REQUEST_CAMERA);
        } catch (Exception localException) {
            Toast.makeText(ActivityAddMemory.this, "Exception:" + localException, Toast.LENGTH_SHORT).show();
        }
    }
    
    
    //GET PATH FROM URI IF SELECTED FROM GALLERY
    public String getRealPathFromURI(Uri uri){
        String filePath = "";
        String[] filePahColumn = {MediaStore.Images.Media.DATA};
        Cursor cursor = getContentResolver().query(uri, filePahColumn, null, null, null);
        if (cursor != null) {
            if(cursor.moveToFirst()){
                int columnIndex = cursor.getColumnIndex(filePahColumn[0]);
                filePath = cursor.getString(columnIndex);
            }
            cursor.close();
        }
        return filePath;
    }
    
    
    //DO WHAT YOU WANT WHEN RESULT IS RETURNED
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
    
        if(resultCode == RESULT_OK) {
    
            String path=null;
            Uri uri;
    
            if (intent == null || intent.getData() == null)
                uri = this.imageUri;
            else
                uri = intent.getData();
    
            if(requestCode == SELECT_FILE) {
                path = getRealPathFromURI(uri);
            } else if(requestCode == REQUEST_CAMERA){
                path = uri.getEncodedPath();
            }
    
            //THIS IS THE PATH YOU WOULD NEED
    
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-29
      • 1970-01-01
      • 2016-12-29
      • 2011-01-31
      • 2011-08-06
      • 2018-10-12
      相关资源
      最近更新 更多