获取从图库中选择的图像的路径(在SD卡上)

时间:2017-04-07 03:47:13

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

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

最推荐的方法(@Commonsware)是使用import { EitherIO, liftEither, liftIO, runEitherIO } from './EitherIO' // ... // prog :: () -> Either Error String const prog = () => runEitherIO(EitherIO(read('#app')) .chain(R.compose(liftIO, write('Hello world')))) either (throwError, console.log) (prog()) 并调用ContentResolver,所以我尝试从openInputStream()读取字节然后创建临时文件并使用该路径, 没运气。我的“字节读取:”openInputStream()调用显示0字节读取。

我还尝试了thisthisthisthisthisthis,但都没有效果。很多这些答案导致调用System.err.println,问题是,我不关心显示图像,我只是需要路径!!。

请帮助!

到目前为止

代码:

BitmapFactory#decodeStream()

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

 @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;
}

3 个答案:

答案 0 :(得分:2)

应用程序无法直接访问SD卡的任何内容。因此,即使你能得到一条“路径”。某种程度上,你的应用程序无法从该位置读取任何内容。

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

您绝对可以将文件复制到own cache directory,然后根据图片执行任何操作。

答案 1 :(得分:1)

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

  1. 使用元素的子元素以XML格式指定存储区域和路径的内容。例如,以下pathsmann告诉FileProvider您打算为私有文件区域的images /子目录请求内容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);
    

答案 2 :(得分:0)

不同手机有不同的行为。经过大量的研究和尝试不同的可能性,我想出了一个解决方案,它正在我测试的所有手机上工作(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

    }

}