Android getPath() from Uri not working - android

On huawei honor 8 with android 7.0 the uri.getPath() returns something like /external/file/3344 instead of real path of the file.This code also works fine on many devices and also on android emulator with android 7.0 and uri.getPath() returns /storage/emulated/0/PCalculator/main.js but not on honor 8. I used Intent to choose a file in my program as below :
private void fileBrowse(){
Intent intent = new Intent();
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser
(intent,"Open File"),RCODE_OPENFILE);
}
And in onActivityResult I want to read the file as below :
public void onActivityResult(int requestCode,int resultCode,Intent data) {
super.onActivityResult(requestCode,resultCode,data);
switch(requestCode){
case RCODE_OPENFILE:
if(resultCode == RESULT_OK &&
data != null && data.getData() != null){
fileOpen(data.getData());
}
break;
}
}
And the fileOpen function :
private void fileOpen(Uri uri){
File mFile = new File(uri.getPath());
StringBuilder mText = new StringBuilder();
try {
BufferedReader br = new BufferedReader(new FileReader(mFile));
String line;
while ((line = br.readLine()) != null) {
mText.append(line);
mText.append('\n');
}
br.close();
}
catch (IOException e) {
e.printStackTrace();
}
etCode.setText(mText);
tvTitle.setText(mFile.getName());
}

Related

Android storage access framework returning "raw" path

Trying to use the Storage access framework to select a file from the device (an html file that I wan't to parse) but it returns a file path that doesn't appear to be a content URI (/document/raw:/storage/emulated/0/Download/test.html) and that errors when I use it with the content resolver.
Intent to fetch file:
boolean alreadyHasReadPermissions = hasPermission(Manifest.permission.READ_EXTERNAL_STORAGE);
if (alreadyHasReadPermissions) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("text/html");
try {
activity.startActivityForResult(intent, fileChooserResultCode);
}catch(ActivityNotFoundException e){
Toast.makeText(activity, R.string.unable_to_open_file_picker, Toast.LENGTH_LONG).show();
}
}
Code to read a file:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==fileChooserResultCode){
if(resultCode == Activity.RESULT_OK && data.getData()!=null) {
String contentUriString = data.getData().getPath();
try {
Uri contentUri = Uri.parse(contentUriString);
InputStream inputStream = getContentResolver().openInputStream(contentUri); // <<< Errors with FileNotFoundException
BufferedReader bf = new BufferedReader(new InputStreamReader(inputStream));
...
}catch (NullPointerException | IOException e){
Toast.makeText(this, R.string.unable_to_open_file, Toast.LENGTH_LONG).show();
}
}
}
}
Delete:
String contentUriString = data.getData().getPath();
and delete:
Uri contentUri = Uri.parse(contentUriString);
And change:
InputStream inputStream = getContentResolver().openInputStream(contentUri);
to:
InputStream inputStream = getContentResolver().openInputStream(data.getData());
IOW, do not call getPath() on a Uri.

File Object is Not Getting Created

I am giving file browser to user to select file. On onActivityResult I am getting file path as - /file/sdcard/Android/data/com.coca_cola.android.conferenceapp/cache/Conference/export.txt. When I try to create file object on this I am not able to create. When I remove /file/ and create file object on sdcard/Android/data/com.coca_cola.android.conferenceapp/cache/Conference/export.txt its getting created. But I cant hardcode to remove /file/ from filepath as on other device it will be giving some other path. below is the code
private void readContactFromFile(String path) {
StringBuilder text = new StringBuilder();
try {
String st = "/file/sdcard/Android/data/com.coca_cola.android.conferenceapp/cache/Conference/export.txt";
File file = new File(st);
if (file.exists()) {
Log.v("TTT", "file exist");
}
Log.v("TTT", file.toString());
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
while ((line = br.readLine()) != null) {
text.append(line);
Log.i("Test", "text : " + text + " : end");
text.append('\n');
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
and I am getting path on OnActivityResult
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
switch (requestCode) {
case REQUEST_PICK_FILE:
Uri uri = data.getData();
String path = data.getData().getPath();
Log.v("PATH", path);
readContactFromFile(path);
break;
}
}
}
And this is how I am calling for opening file browser
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*"); //all files
//intent.setType("text/xml"); //XML file only
intent.addCategory(Intent.CATEGORY_OPENABLE);
try {
startActivityForResult(Intent.createChooser(intent, "Select a File to Upload"), REQUEST_PICK_FILE);
} catch (android.content.ActivityNotFoundException ex) {
// Potentially direct the user to the Market with a Dialog
Toast.makeText(this, "Please install a File Manager.", Toast.LENGTH_SHORT).show();
}
How can I get the perfect path or How can I remove this issue?
Thanks in Advance
Because of the circumstance that the path differs on different devices you should use the frameworks api to retrieve the appropiate path for you.
Have a look at the Environment class.
Instead of using hardcoded string path get the path using Environment class
File file=new File(String.valueOf(Environment.getExternalStorageDirectory())+"YOUR_REQUIRED_FILE_PATH");
It will not defer from device to device.
Hope this helps :)

Android open text file to read after Intent.ACTION_GET_CONTENT

The flow is:
The user needs to select text file for use and the default Android explorer whatever pops up.
Then I want to store string containing the file name, to actually open the file for reading.
I want to open that file and rewrite him to new file on app internal storage.
I want to open the new created file from app internal storage.
Bonus 1 - If it's now .txt file but .doc, I want to convert him to regular .txt file in step 3 above of rewriting.
Bonus 2 - How to handle large text files?
Here's the code:
// 1. Start with user action pressing on button to select file
addButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
startActivityForResult(intent, PICKFILE_RESULT_CODE);
}
});
// 2. Come back here
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PICKFILE_RESULT_CODE) {
// Get the Uri of the selected file
Uri uri = data.getData();
String filePathName = "WHAT TODO ?";
LaterFunction(filePathName);
}
}
// 3. Later here
public void LaterFunction(String filePathName) {
BufferedReader br;
FileOutputStream os;
try {
br = new BufferedReader(new FileReader("WHAT TODO ?"));
//WHAT TODO ? Is this creates new file with
//the name NewFileName on internal app storage?
os = openFileOutput("newFileName", Context.MODE_PRIVATE);
String line = null;
while ((line = br.readLine()) != null) {
os.write(line.getBytes());
}
br.close();
os.close();
lastFunction("newFileName");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
// 4. And in the end here
public void lastFunction(String newFileName) {
//WHAT TODO? How to read line line the file
//now from internal app storage?
}
Step #1: Delete String filePathName = "WHAT TODO ?";
Step #2: Change LaterFunction(filePathName); to LaterFunction(uri);
Step #3: Change br = new BufferedReader(new FileReader("WHAT TODO ?")); to br = new BufferedReader(new InputStreamReader(getContentResolver().openInputStream(uri));
That is the minimum necessary to address your question.
However, a MIME type of */* will match any type of file, not just text files. Binary files should not be copied using readLine(). If you only want plain text files, use text/plain instead of */*.
For those who struggle to fix that code here is the fixed one
ab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
startActivityForResult(intent, PICKFILE_RESULT_CODE);
}
});
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICKFILE_RESULT_CODE) {
Uri uri = data.getData();
LaterFunction(uri);
}
}
public void LaterFunction(Uri uri) {
BufferedReader br;
FileOutputStream os;
try {
br = new BufferedReader(new InputStreamReader(getContentResolver().openInputStream(uri)));
//WHAT TODO ? Is this creates new file with
//the name NewFileName on internal app storage?
os = openFileOutput("newFileName", Context.MODE_PRIVATE);
String line = null;
while ((line = br.readLine()) != null) {
os.write(line.getBytes());
Log.w("nlllllllllllll",line);
}
br.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}

Android : How to get file data from a Filechooser?

I have a filechooser that I call in a webview in order to upload a file.
The method allowing me to retrieve the file in my filechooser activity is as follows :
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
// TODO Auto-generated method stub
super.onListItemClick(l, v, position, id);
Option o = adapter.getItem(position);
if (o.isFolder() || o.isParent()) {
currentDir = new File(o.getPath());
fill(currentDir);
} else {
//onFileClick(o);
fileSelected = new File(o.getPath());
Intent intent = new Intent();
intent.putExtra("fileSelected", fileSelected.getAbsolutePath());
setResult(Activity.RESULT_OK, intent);
finish();
}
}
This only allows me to get the path in the onActivityResult of my webview (which calls my filechooser to upload file).
The method onActivityResult is given by the code below.
If I use another application installed in my phone other than my filechooser I use :
Uri result = intent == null || resultCode != RESULT_OK ? null : intent.getData();
then the result is sent by:
this.mUploadMessage.onReceiveValue(uri);
Since then, it works normally. But with my filechooser intent.getData () equals to null.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == FILECHOOSER_RESULTCODE) {
if (null == this.mUploadMessage) {
return;
}
if (resultCode != RESULT_OK) {
mUploadMessage.onReceiveValue(null);
var = 0;
return;
}
// Toast.makeText(getApplicationContext() , "onActivityResult()" + String.valueOf(requestCode) ,Toast.LENGTH_LONG).show();
// Uri result = intent == null || resultCode != RESULT_OK ? null : intent.getData();
// this.mUploadMessage = null;
String fileSelected = intent.getStringExtra("fileSelected");
Bundle result = intent.getExtras();
//result = Uri.parse(fileSelected);
//this.mUploadMessage.onReceiveValue(result);
if (resultCode == RESULT_OK) {
if (intent != null) {
// Get the URI of the selected file
final Uri uri = intent.getData();
Log.i("TOTOTOT", "Uri = " + uri.toString());
Toast.makeText(this, fileSelected + " " + uri.toString() , Toast.LENGTH_SHORT).show();
this.mUploadMessage.onReceiveValue(uri);
}
}
super.onActivityResult(requestCode, resultCode, intent);
}
}
What should I return in my two methods in order to retrieve both data and path, not only the path of the sent file ? Should it be all the bundle or do you know how to get Data while using Intent.getData()?
What is need to get data from directory selected inside onActivityResult()
You got path selected so you can read file from there which you want ..
Use this method to read file as a string
private String readURLFromPath(File filePath){
String dataString = "";
// i have kept text.txt in the sd-card
if (file.exists()) // check if file exist
{
// Read text from file
StringBuilder text = new StringBuilder();
try {
BufferedReader br = new BufferedReader(new FileReader(filePath));
String line;
while ((line = br.readLine()) != null) {
text.append(line);
text.append('\n');
}
} catch (IOException e){
// You'll need to add proper error handling here
}
// Set the text
dataString = text.toString();
}
return dataString ;
}
this method will return data as a string now you can send this string data on server...
the solution is to Get content uri from file path in android as mentioned Get content uri from file path

Open text file using ACTION_OPEN_DOCUMENT

I'm trying to set an 'EditText' to the contents of a simple txt file. After looking at the developer page I stumbled across some code that gets a photo. I edited to what I thought would suit my needs but it doesn't work:
private void importText(){
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.setType("text/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(intent, 0);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 0 && resultCode == RESULT_OK) {
String textContent = data.getDataString();
mEditText.setText(textContent);
}
}
What this does is it puts the string name of what appears to be the files location in the EditText not the contents of it. My app right now only supports API 19 so I thought I would be able to use this as a feature. Is this function possible using ACTION_OPEN_DOCUMENT or do I need to do something else?
Use following method to read data :
public static String readTextFromUri(Context context, Uri uri) throws IOException {
StringBuilder stringBuilder = new StringBuilder();
try (InputStream inputStream =
context.getContentResolver().openInputStream(uri);
BufferedReader reader = new BufferedReader(
new InputStreamReader(Objects.requireNonNull(inputStream)))) {
String line;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
}
}
return stringBuilder.toString();
}
and get uri from given intent in onActivityResult method :
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 0 && resultCode == RESULT_OK) {
Uri uri = data.getData();
String myText = readTextFromUri(yourContext , uri);
}
}
You need to retrieve an Input Stream from the Uri as explained in the documentation. (Section "Get an Input Stream").

Categories

Resources