我根本无法获得从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字节读取。
我还尝试了this,this,this,this,this和this,但都没有效果。很多这些答案导致调用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;
}
答案 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 你应该这样写:
使用元素的子元素以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>
第三步:文件是你的路径
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
}
}