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/
を取得します。しかし、このパスではファイルを取得できません。 File
を返すPathToFile()
というメソッドを作成しました:
private File PathToFile(String path) {
File tempFileToUpload;
tempFileToUpload = new File(path);
return tempFileToUpload;
}
私がやろうとしていることは、ユーザーがFile
を選択できるようにすることですDropBox
、Drive
、SDCard
、Mega
など...そして、私はそれを正しく行う方法を見つけられないので、Path
を取得しようとしましたこのFile
によるPath
...が機能しないため、File
自体を取得し、プログラムでこのFile
を使用して、プログラムで私はCopy
thisまたはDelete
を取得することをお勧めします。
私の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
を取得しています:
Java.lang.RuntimeException:結果ResultInfo {who = null、request = 131073、result = -1、data = Intent {dat = file:/// path typ = text/plain flg = 0x3}}をアクティビティ{infoに配信できませんでした.androidhive.tabsswipe/info.androidhive.tabsswipe.MainActivity2}:Java.lang.NullPointerException
これはIntent
で、ファイル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();
を実行し、名前を保持します。 content_describer.getLastPathSegment();
でTextView
でそれを使用するパス(@YSはその関数を知らなかったのはすごかったです)、私はFile
を呼び出して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","....");
}
}
ご協力いただきありがとうございます。皆さんと一緒に作成したこのコードをお楽しみください:)
ステップ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
はonActivityResult()
で返されるIntent
です。
それでも解決しない場合は、次の方法を使用してください。
_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);
}
_
これらの2つの方法の少なくとも1つで、正しいフルパスを取得できます。
ステップ3-ファイルをコピー:
あなたが望むのは、ある場所から別の場所にファイルをコピーすることです。
これを行うには、ソースと宛先の両方の場所の絶対ファイルパスが必要です。
まず、getPath()
メソッドまたはuri.getPath()
のいずれかを使用して絶対ファイルパスを取得します。
_String src = getPath(uri); /* Method defined above. */
_
または
_Uri uri = data.getData();
String src = uri.getPath();
_
次に、次のように2つの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に対する回答-彼がしたことは、 content を返すopenInputStream()
というメソッドを使用することですUri
(ファイルまたはURLを表すUri
)。
別の有望なアプローチ-FileProvider
:
別のアプリからファイルを取得する方法はもう1つあります。アプリが FileProvider
を介してファイルを共有する場合、特定の情報を保持する FileDescriptor
オブジェクトを保持することができます。このファイル。
これを行うには、次の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
はParcelFileDescriptor
です。
参照:
1。Common Intents-File Storage 。
2。FileChannel
。
。FileProvider
。
4。共有ファイルのリクエスト 。
ユーザーがフォルダから画像を選択できるように同じことをしました:
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);
}
}
)画像ファイルのパスを取得し、画像のパスで必要な操作を行うアクティビティの結果:
@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カード、Googleドライブなどに取得することができます... :
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());
}
}
結論:コードは画像パスで動作しますが、あらゆる種類のファイルで動作します。
これが問題の解決に役立つことを願っています。
平和。
@ CommonsWare既に述べたように、AndroidはUri
を返します。これはファイルパスよりも抽象的な概念です。
単純なファイルパスも記述できますが、アクセスされるリソースを記述することもできますthroughアプリケーション(content://media/external/audio/media/710
など)。
ユーザーが電話からファイルを選択してアプリケーションから読み取るようにしたい場合は、ファイルを要求して(正しく行ったように)、ContentResolver
を使用してInputStream
は、ピッカーによって返されるUri
を表します。
次に例を示します。
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();
}
}
}
}
}
重要:一部のプロバイダー(Dropboxなど)は、外部ストレージにデータを保存/キャッシュします。マニフェストでAndroid.permission.READ_EXTERNAL_STORAGE
- permissionを宣言する必要があります。そうしないと、ファイルが存在していてもFileNotFoundException
を取得できます。
更新:はい、1つのストリームから読み取り、別のストリームに書き込むことでファイルをコピーできます。
// Error handling is omitted for shorter code!
Uri content_describer = data.getData();
InputStream in = null;
OutputStream out = null;
try {
// open the user-picked file for reading:
in = getContentResolver().openInputStream(content_describer);
// open the output-file:
out = new FileOutputStream(new File("some/path/to/a/writable/file"));
// copy the content:
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
// Contents are copied!
} finally {
if (in != null) {
in.close();
}
if (out != null){
out.close();
}
}
ファイルは削除できない可能性があります。ファイルはbelongではないため、ファイルを共有したアプリケーションに属しているためです。そのため、所有アプリケーションはファイルを削除する責任があります。
このメソッドでonActivityResultで返されたURIを渡す
private String getPath(Uri contentURI) {
String result;
Cursor cursor = getActivity().getContentResolver().query(contentURI,
null, null, null, null);
if (cursor == null) {
result = contentURI.getPath();
} else {
cursor.moveToFirst();
int idx = cursor
.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
result = cursor.getString(idx);
cursor.close();
}
return result;
}
A Uri
はファイルではありません 。 Uri
はWebサーバーのURLに近いです。これは不透明なアドレスであり、「サーバー」(またはこの場合はContentProvider
)に対してのみ意味を持ちます。
InputStream
を使用してWeb URLで表されるバイトを読み込むように、InputStream
を使用してUri
で表されるバイトを読み込みます。 ContentResolver
でopenInputStream()
を呼び出すことにより、このようなストリームを取得します。