我试图在我的Android项目中实现文件选择器。到目前为止我能做的是:
Intent chooseFile;
Intent intent;
chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
chooseFile.setType("*/*");
intent = Intent.createChooser(chooseFile, "Choose a file");
startActivityForResult(intent, PICKFILE_RESULT_CODE);
然后在我的onActivityResult()
switch(requestCode){
case PICKFILE_RESULT_CODE:
if(resultCode==-1){
Uri uri = data.getData();
String filePath = uri.getPath();
Toast.makeText(getActivity(), filePath,
Toast.LENGTH_LONG).show();
}
break;
}
这是打开文件选择器,但它不是我想要的。例如,我想选择一个文件(.txt),然后获取File
然后使用它。有了这段代码,我想我会得到完整路径,但它并没有发生;例如,我得到:/document/5318/
。但是通过这条路径,我无法获得该文件。我创建了一个名为PathToFile()
的方法,它返回File
:
private File PathToFile(String path) {
File tempFileToUpload;
tempFileToUpload = new File(path);
return tempFileToUpload;
}
我尝试做的是让用户从任何地方选择File
,DropBox
,Drive
,SDCard
,Mega
,等等...而且我找不到正确的方法,我试图获得Path
然后通过此File
获得Path
...但它没有& #39;工作,所以我认为最好是获取File
本身,然后使用此File
以编程方式Copy
这个或Delete
。< / p>
我的Intent
Intent chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
chooseFile.addCategory(Intent.CATEGORY_OPENABLE);
chooseFile.setType("text/plain");
startActivityForResult(
Intent.createChooser(chooseFile, "Choose a file"),
PICKFILE_RESULT_CODE
);
在那里我有一个问题,因为我不知道支持text/plain
的是什么,但我会调查它,但它并不重要那一刻。
在我的onActivityResult()
上,我使用了与@Lukas Knuth answer相同的内容,但我不知道是否可以使用Copy
File
来SDcard
另一部分来自我的@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICKFILE_RESULT_CODE && resultCode == Activity.RESULT_OK){
Uri content_describer = data.getData();
//get the path
Log.d("Path???", content_describer.getPath());
BufferedReader reader = null;
try {
// open the user-picked file for reading:
InputStream in = getActivity().getContentResolver().openInputStream(content_describer);
// now read the content:
reader = new BufferedReader(new InputStreamReader(in));
String line;
StringBuilder builder = new StringBuilder();
while ((line = reader.readLine()) != null){
builder.append(line);
}
// Do something with the content in
text.setText(builder.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
我正在等待他的回答。
getPath()
来自@ Y.S的 String[] projection = { MediaStore.Files.FileColumns.DATA };
Cursor cursor = getActivity().getContentResolver().query(content_describer, projection, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(projection[0]);
cursor.moveToFirst();
cursor.close();
Log.d( "PATH-->",cursor.getString(column_index));
。
我这样做:
NullPointerException
获得Intent
:
java.lang.RuntimeException:将结果ResultInfo {who = null,request = 131073,result = -1,data = Intent {dat = file:/// path typ = text / plain flg = 0x3}}发送到activity {info.androidhive.tabsswipe / info.androidhive.tabsswipe.MainActivity2}:java.lang.NullPointerException
这是text/plain
,我只接受文件Intent chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
chooseFile.addCategory(Intent.CATEGORY_OPENABLE);
chooseFile.setType("text/plain");
startActivityForResult(
Intent.createChooser(chooseFile, "Choose a file"),
PICKFILE_RESULT_CODE
);
。
onActivityResult()
在我的URI
我创建了一个Intent
我获取了File
的数据,我创建了一个content_describer.getPath();
,其中我保存了绝对路径正在执行TextView
,然后我保留了content_describer.getLastPathSegment();
File
中使用它的路径名称(这真是太棒了@YS不知道该功能) ,我创建了第二个destination
,我打电话给AbsolutePath
,我发送File
即可创建此@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICKFILE_RESULT_CODE && resultCode == Activity.RESULT_OK){
Uri content_describer = data.getData();
String src = content_describer.getPath();
source = new File(src);
Log.d("src is ", source.toString());
String filename = content_describer.getLastPathSegment();
text.setText(filename);
Log.d("FileName is ",filename);
destination = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Test/TestTest/" + filename);
Log.d("Destination is ", destination.toString());
SetToFolder.setEnabled(true);
}
}
。
source file
此外,我已创建了一项功能,您必须先发送我们之前创建的destination file
和private void copy(File source, File destination) throws IOException {
FileChannel in = new FileInputStream(source).getChannel();
FileChannel out = new FileOutputStream(destination).getChannel();
try {
in.transferTo(0, in.size(), out);
} catch(Exception e){
Log.d("Exception", e.toString());
} finally {
if (in != null)
in.close();
if (out != null)
out.close();
}
}
,然后将其复制到新文件夹。
destination file
我还创建了一个函数,告诉我这个文件夹是否存在(我必须发送private void DirectoryExist (File destination) {
if(!destination.isDirectory()) {
if(destination.mkdirs()){
Log.d("Carpeta creada","....");
}else{
Log.d("Carpeta no creada","....");
}
}
,如果它不存在我创建这个文件夹,如果它存在不是我什么都不做。
Task.WhenAll
再次感谢您的帮助,希望您喜欢与大家一起制作的代码:)
答案 0 :(得分:31)
第1步 - 使用隐式Intent
:
要从设备中选择文件,您应使用隐式Intent
Intent chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
chooseFile.setType("*/*");
chooseFile = Intent.createChooser(chooseFile, "Choose a file");
startActivityForResult(chooseFile, PICKFILE_RESULT_CODE);
第2步 - 获取绝对文件路径:
要从Uri
获取文件路径,请先尝试使用
Uri uri = data.getData();
String src = uri.getPath();
其中data
是Intent
中返回的onActivityResult()
。
如果不起作用,请使用以下方法:
public String getPath(Uri uri) {
String path = null;
String[] projection = { MediaStore.Files.FileColumns.DATA };
Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
if(cursor == null){
path = uri.getPath()
}
else{
cursor.moveToFirst();
int column_index = cursor.getColumnIndexOrThrow(projection[0]);
path = cursor.getString(column_index);
cursor.close();
}
return ((path == null || path.isEmpty()) ? (uri.getPath()) : path);
}
这两种方法中至少有一种应该能为您提供正确的完整路径。
第3步 - 复制文件:
我认为,您想要的是将文件从一个位置复制到另一个位置。
要做到这一点,绝对有必要拥有源位置和目标位置的绝对文件路径。
首先,使用我的getPath()
方法或uri.getPath()
获取绝对文件路径:
String src = getPath(uri); /* Method defined above. */
或
Uri uri = data.getData();
String src = uri.getPath();
然后,按如下方式创建两个File
个对象:
File source = new File(src);
String filename = uri.getLastPathSegment();
File destination = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/CustomFolder/" + filename);
其中CustomFolder
是外部驱动器上要复制文件的目录。
然后使用以下方法将文件从一个地方复制到另一个地方:
private void copy(File source, File destination) {
FileChannel in = new FileInputStream(source).getChannel();
FileChannel out = new FileOutputStream(destination).getChannel();
try {
in.transferTo(0, in.size(), out);
} catch(Exception){
// post to log
} finally {
if (in != null)
in.close();
if (out != null)
out.close();
}
}
试试这个。这应该有用。
注意:与Lukas的回答相比 - 他所做的是使用名为openInputStream()
的方法,该方法返回{{> 的{em>内容 1}},Uri
代表文件或网址。
另一种有前途的方法 - Uri
:
还有一种方法可以从另一个应用程序获取文件。如果应用程序通过FileProvider
共享其文件,则可以获取保存有关此文件的特定信息的FileDescriptor
对象。
为此,请使用以下FileProvider
:
Intent
和您的Intent mRequestFileIntent = new Intent(Intent.ACTION_GET_CONTENT);
mRequestFileIntent.setType("*/*");
startActivityForResult(mRequestFileIntent, 0);
:
onActivityResult()
其中@Override
public void onActivityResult(int requestCode, int resultCode,
Intent returnIntent) {
// If the selection didn't work
if (resultCode != RESULT_OK) {
// Exit without doing anything else
return;
} else {
// Get the file's content URI from the incoming Intent
Uri returnUri = returnIntent.getData();
/*
* Try to open the file for "read" access using the
* returned URI. If the file isn't found, write to the
* error log and return.
*/
try {
/*
* Get the content resolver instance for this context, and use it
* to get a ParcelFileDescriptor for the file.
*/
mInputPFD = getContentResolver().openFileDescriptor(returnUri, "r");
} catch (FileNotFoundException e) {
e.printStackTrace();
Log.e("MainActivity", "File not found.");
return;
}
// Get a regular file descriptor for the file
FileDescriptor fd = mInputPFD.getFileDescriptor();
...
}
}
是mInputPFD
。
<强>参考文献:强>
1。 Common Intents - File Storage。
2。 FileChannel
。
3。 FileProvider
。
答案 1 :(得分:5)
我做了同样的事情让用户从文件夹中选择一张图片:
1)有一个按钮OPEN:
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_open:
myOpenImagePicker();
break;
}
}
2)打开图片文件夹功能:
@SuppressLint("InlinedApi")
public void myOpenImagePicker() {
if (Build.VERSION.SDK_INT < 19) {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(
Intent.createChooser(intent, "Select Picture"),
SELECT_FOLDER);
} else {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivityForResult(intent, SELECT_FOLDER);
}
}
3)活动结果我获取图像文件路径并使用图像路径执行任何操作:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case SELECT_FOLDER:
if (resultCode == RESULT_OK && data != null) {
Uri originalUri = data.getData();
String id01 = W_ImgFilePathUtil.getPath(
getApplicationContext(), originalUri);
Bitmap unscaledBitmap = W_ImgScalingUtil.decodeResource(id01,
xdrawing.getViewWidth(), xdrawing.getViewHeight(),
ScalingLogic.FIT);
if (unscaledBitmap == null) {
zprefsutil.ShowToast("IMAGE ERROR", 1);
} else {
setExternalScaledBitmap(W_ImgScalingUtil
.createScaledBitmap(unscaledBitmap,
xdrawing.getViewWidth(),
xdrawing.getViewHeight(), ScalingLogic.FIT));
unscaledBitmap.recycle();
xdrawing.invalidate();
}
}
break;
default:
break;
}
}
4)现在是最重要的部分,W_ImgFilePathUtil类,代码不是来自我,但它允许您检索任何选定文件的完整路径,无论是在SD卡,谷歌驱动器,... :强>
public class W_ImgFilePathUtil {
/**
* Method for return file path of Gallery image
*
* @param context
* @param uri
* @return path of the selected image file from gallery
*/
@SuppressLint("NewApi")
public static String getPath(final Context context, final Uri uri) {
// check here to KITKAT or new version
final boolean isKitKatorUp = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKatorUp && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/"
+ split[1];
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"),
Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[] { split[1] };
return getDataColumn(context, contentUri, selection,
selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
// Return the remote address
if (isGooglePhotosUri(uri))
return uri.getLastPathSegment();
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
/**
* Get the value of the data column for this Uri. This is useful for
* MediaStore Uris, and other file-based ContentProviders.
*
* @param context
* The context.
* @param uri
* The Uri to query.
* @param selection
* (Optional) Filter used in the query.
* @param selectionArgs
* (Optional) Selection arguments used in the query.
* @return The value of the _data column, which is typically a file path.
*/
public static String getDataColumn(Context context, Uri uri,
String selection, String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = { column };
try {
cursor = context.getContentResolver().query(uri, projection,
selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
final int index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
/**
* @param uri
* The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
*/
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri
.getAuthority());
}
/**
* @param uri
* The Uri to check.
* @return Whether the Uri authority is DownloadsProvider.
*/
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri
.getAuthority());
}
/**
* @param uri
* The Uri to check.
* @return Whether the Uri authority is MediaProvider.
*/
public static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri
.getAuthority());
}
/**
* @param uri
* The Uri to check.
* @return Whether the Uri authority is Google Photos.
*/
public static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri
.getAuthority());
}
}
结论:代码适用于图像路径,但确实适用于任何类型的文件。
希望这有助于解决您的问题。
和平。
答案 2 :(得分:4)
正如 @CommonsWare 已经注意到的那样,Android会返回Uri
,这是一个比文件路径更抽象的概念。
它也可以描述一个简单的文件路径,但它也可以描述通过应用程序访问的资源(如content://media/external/audio/media/710
)。
如果您希望用户从手机中选择任何文件以从您的应用程序中读取它,您可以通过询问文件(正如您所做的那样)来执行此操作,然后使用ContentResolver
获取{ {1}}表示选择器返回的InputStream
。
以下是一个例子:
Uri
重要:某些提供商(如Dropbox)将其数据存储/缓存在外部存储上。您需要在清单中声明Intent chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
// Ask specifically for something that can be opened:
chooseFile.addCategory(Intent.CATEGORY_OPENABLE);
chooseFile.setType("*/*");
startActivityForResult(
Intent.createChooser(chooseFile, "Choose a file"),
PICKFILE_REQUEST_CODE
);
// And then somewhere, in your activity:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICKFILE_REQUEST_CODE && resultCode == RESULT_OK){
Uri content_describer = data.getData();
BufferedReader reader = null;
try {
// open the user-picked file for reading:
InputStream in = getContentResolver().openInputStream(content_describer);
// now read the content:
reader = new BufferedReader(new InputStreamReader(in));
String line;
StringBuilder builder = new StringBuilder();
while ((line = reader.readLine()) != null){
builder.append(line);
}
// Do something with the content in
some_view.setText(builder.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
- 权限,否则即使文件存在,您也会获得android.permission.READ_EXTERNAL_STORAGE
。
更新:是的,您可以通过从一个流中读取文件并将其写入另一个流来复制该文件:
FileNotFoundException
可能无法删除文件,因为文件不属于属于,它属于与您共享文件的应用程序。因此,拥有的应用程序负责删除文件。
答案 3 :(得分:2)
在此方法中传递onActivityResult中返回的URI
<li></li>
答案 4 :(得分:2)
使用 ActivityResultLauncher
是这样的:
ActivityResultLauncher<Intent> startActivityForResult = requireActivity().registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
if (result.getResultCode() == Activity.RESULT_OK) {
Intent data = result.getData();
Uri contentUri = data.getData();
...
}
});
用法示例:
Intent data = new Intent(Intent.ACTION_GET_CONTENT);
data.addCategory(Intent.CATEGORY_OPENABLE);
data.setType("*/*");
Intent intent = Intent.createChooser(data, "Choose a file");
startActivityForResult.launch(intent);
需要以下依赖项(有或没有 -ktx
):
implementation "androidx.activity:activity:1.2.3"
答案 5 :(得分:1)
A Uri
is not a file。 import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
x = np.arange(0,10,.05)
wave = np.sin(x)
noise = np.random.normal(0,.05,200)
y = noise + wave
noise2 = np.random.normal(0,.05,200)
y2 = noise2 + wave
noise3 = np.random.normal(0,.05,200)
y3 = noise3 + wave
y_avg = (np.array(y) + np.array(y2) + np.array(y3)) / 3
for i in range(5, 15):
mean = np.mean(y_avg)
print mean
plt.plot(x, y, color = 'red', label= 'line 1')
plt.plot(x, y2, color = 'pink', label = 'line 2')
plt.plot(x, y3, color = 'magenta', label = 'line 3')
plt.plot(x, y_avg, color = 'blue', label = 'average')
plt.legend()
plt.show()
更接近Web服务器URL。它是一个不透明的地址,只对服务器&#34;有意义。 (或者在这种情况下,Uri
)。
就像使用ContentProvider
读取Web URL表示的字节一样,使用InputStream
读取InputStream
表示的字节。您可以通过在Uri
上调用openInputStream()
来获得此类流。
答案 6 :(得分:1)
这里是实现文件选择器并将所选文件移动到另一个位置(例如图片)的方法。
首先,在点击侦听器上向按钮添加文件选择器,如下所示:
用于选择文件的按钮:
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_choose_file:
showFileChooser();
break;
}
}
private String filePath = null;
private File sourceFile;
private static final int FILE_SELECT_CODE = 0;
private void showFileChooser() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
try {
startActivityForResult(
Intent.createChooser(intent, "Select a File to Copy"),
FILE_SELECT_CODE);
} catch (android.content.ActivityNotFoundException ex) {
Toast.makeText(this, "Please install a File Manager.",
Toast.LENGTH_SHORT).show();
}
}
然后像这样处理onActivityResult:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case FILE_SELECT_CODE:
if (resultCode == RESULT_OK) {
// Get the Uri of the selected file
Uri uri = data.getData();
File file = new File(getCacheDir(), getFileName(uri));
int maxBufferSize = 1 * 1024 * 1024;
try {
InputStream inputStream = getContentResolver().openInputStream(uri);
Log.e("InputStream Size","Size " + inputStream);
int bytesAvailable = inputStream.available();
int bufferSize = Math.min(bytesAvailable, maxBufferSize);
final byte[] buffers = new byte[bufferSize];
FileOutputStream outputStream = new FileOutputStream(file);
int read = 0;
while ((read = inputStream.read(buffers)) != -1) {
outputStream.write(buffers, 0, read);
}
Log.e("File Size","Size " + file.length());
inputStream.close();
outputStream.close();
file.getPath();
Log.e("File Path","Path " + file.getPath());
file.length();
Log.e("File Size","Size " + file.length());
if(file.length() > 0){
sourceFile = file;
saveFile(sourceFile);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (OutOfMemoryError e) {
e.printStackTrace();
}
} else {
}
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
private void saveFile (File sourceFile) {
try {
File currentFile = sourceFile;
Bitmap myBitmap = BitmapFactory.decodeFile(currentFile.getAbsolutePath());
String path = currentFile.getAbsolutePath();
String idStr = path.substring(path.lastIndexOf('/') + 1);
File filepath = Environment.getExternalStorageDirectory();
File dir = new File(filepath.getAbsolutePath() + "/" + "yourFolderName" + "/");
if (!dir.exists()) {
dir.mkdirs();
}
String fileName = currentFile.getName();
file = new File(dir, fileName);
if (file.exists()) file.delete();
FileOutputStream fos = new FileOutputStream(file);
myBitmap.compress(CompressFormat.JPEG, 65, fos);
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
注意:请不要忘记将此权限添加到清单文件中。
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
希望这会有所帮助。